0

I'm hoping someone can help me with an issue I have regarding an Apex Trigger that creates a child record when a field of its corresponding master record is set to a particular value. The master object is Opportunity and the child record is a custom object called Ad_Ops_Task__c. My problem is that the following code creates duplicates of the child record when the Opportunity field is set to the value specified in my code below:

trigger CreateAdOpsTask on Opportunity (after update) 
{
    List <Ad_Ops_Task__c> Ad_Ops_Tasks = new List <Ad_Ops_Task__c> ();
    for(Opportunity a: Trigger.new)
        {
        if(a.StageName=='Ad6 - IO Received')
            {
            Ad_Ops_Task__c AOSTask = new Ad_Ops_Task__c ();
            AOSTask.Opportunity__c = a.Id;
            AOSTask.Name = 'AdOps Task - ' + a.Name + ' - ' + a.Media_Plan_Id__c;
            Ad_Ops_Tasks.add(AOSTask);
            }
        }
insert Ad_Ops_Tasks;
}
  • This code in itself isn't going to create duplicate child records, it's simply going to create a new Ad_Ops_Task__c record for each opportunity in that stage. Do you have a workflow rule on this object that updates fields on the parent opportunity record? Or are you saying that there should only ever be one child record for the opportunity in this stage? – Mark Pond Sep 8 '15 at 16:32
  • 1
    The code isn't checking that the value for stagename has changed though... so once an Opp reaches that stage, every edit to the Opp will create a new Ad_Ops_Task__c – Doug B Sep 8 '15 at 16:35
  • Thanks for the quick replies Mark and Doug! There is an existing trigger on the Opportunity that modifies fields of the Opportunity when certain criteria are met. There could possibly be multiple Ad_Ops_Task__c objects associated with a single Opportunity, however I'm looking to have only one generated when the Opportunity StageName field is set to 'Ad6 - IO Received.' Other fields may change while the StageName is at this value, so I'd like to prevent duplicates from being created when anything besides the StageName value is changed. – Russell Eutsler Sep 8 '15 at 16:44
0

In addition to comparing the old stagename to the new stagename, you need to ensure that your logic only fires once. Create a class like

public class CreateAdOpsTaskTriggerContext {
  public static boolean executeTrigger=true;
}

Modify your trigger to check the value before executing your logic and then set the executeTrigger variable to false at the end of your logic.

trigger CreateAdOpsTask on Opportunity (after update) {
   if (CreateAdOpsTaskTriggerContext.executeTrigger){
      List <Ad_Ops_Task__c> Ad_Ops_Tasks = new List <Ad_Ops_Task__c> ();

      for (Opportunity oppty: Trigger.new) {

         // get the record out of the oldMap for comparison
         Opportunity oldOppty = (Opportunity)Trigger.oldMap.get(oppty.id);

         // only run this code if the opportunity is in the correct stage, and the stagename has been modified
         if (oppty.StageName == 'Ad6 - IO Received' && oppty.StageName != oldOppty.StageName) {
            Ad_Ops_Task__c AOSTask = new Ad_Ops_Task__c ();
            AOSTask.Opportunity__c = oppty.Id;
            AOSTask.Name = 'AdOps Task - ' + oppty.Name + ' - ' + oppty.Media_Plan_Id__c;
            Ad_Ops_Tasks.add(AOSTask);
         }
      }

      insert Ad_Ops_Tasks;
   }
   CreateAddOpsTaskTriggerContext.executeTrigger = false;
}
  • This seems to be the magic sauce needed to make this work! Adding the public class and checking that the execute trigger variable is false got rid of my duplicates. Many thanks! – Russell Eutsler Sep 8 '15 at 18:22
1

I don't think that's what happening.

From looking at your code, I would think that you aren't checking whether there is an Ad_Ops_Task__c object already associated to that opportunity. You should check to see whether one exists for each.

  • Hey Brian, thanks for the reply! Would it be possible to check to see if the Ad_Ops_Task__c object has been created with modifications to the code above? Per my comment above, there is a second trigger on the Opportunity that is modifying fields of the Opportunity when the StageName is set to this value...again pardon my ignorance on how to accomplish this, I'm not really a programmer at heart (though I have aspirations!) – Russell Eutsler Sep 8 '15 at 16:47
  • 1
    Either a rollup field on the Opportunity, or a query which checks all records in the trigger and pulls a count of how many children of a type are associated with that record. A rollup field would be the easier option. – battery.cord Sep 8 '15 at 16:50
0

If you want to incorporate the usage of the oldMap to detect if the stagename has changed before creating the child record you can do so like this:

trigger CreateAdOpsTask on Opportunity (after update) {

    List <Ad_Ops_Task__c> Ad_Ops_Tasks = new List <Ad_Ops_Task__c> ();

    for (Opportunity oppty: Trigger.new) {

        // get the record out of the oldMap for comparison
        Opportunity oldOppty = (Opportunity)Trigger.oldMap.get(oppty.id);

        // only run this code if the opportunity is in the correct stage, and the stagename has been modified
        if (oppty.StageName == 'Ad6 - IO Received' && oppty.StageName != oldOppty.StageName) {
            Ad_Ops_Task__c AOSTask = new Ad_Ops_Task__c ();
            AOSTask.Opportunity__c = oppty.Id;
            AOSTask.Name = 'AdOps Task - ' + oppty.Name + ' - ' + oppty.Media_Plan_Id__c;
            Ad_Ops_Tasks.add(AOSTask);
        }
    }

    insert Ad_Ops_Tasks;
}

You should also consider the behavior when the stagename moves "past" this stage... can it revert back to this stage? Should another child record be created at that time? Is that behavior you need to account for in this trigger's logic too?

  • Hey Mark, Thanks so much for your response....I was still seeing duplicates however after implementing this modified trigger. The answer from Developer Wonk below seems to have been the key here. Adding the public class and checking the executeTrigger variable seems to have done the trick! – Russell Eutsler Sep 8 '15 at 18:20

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.