0

So I just realized that parent fields are not available on child triggers without querying. But i've tried several different methods and do no get the expected response. I want to create a campaign when the checkbox field Create_Campaign__c is checked.

There is a Budget__c field on Budget_Item__c that is a master-detail to object Budget__c.

These are the 3 variations i have tried:

The current code is the one below and i get required fields are missing [Budget__c]:[Budget__c]

trigger CreateCampaign on Budget_Item__c (after insert, after update)
{
   List<Campaign> ca = new List <Campaign>();
   Set<id> triggerIds = Trigger.newMap.keyset();
   Budget_Item__c ParentData = [select Name, Budget__c, 
                               budget__r.Region__c from 
                               Budget_Item__c where id in :triggerIds];

    for(Budget_Item__c bi : trigger.new)
   {
    if(bi.Create_Campaign__c == true)
    {  
       Campaign c = new Campaign();      
       c.Region__c = ParentData.budget__r.Region__c;
       //other fields
       ca.add(c);
    }
   }
    Database.insert(ca, false);
}

2

 for(Budget_Item__c bi : [select id, budget__r.region__c ... from Budget_Item__c 
                           where Id in: trigger.new])
   {
    Campaign c = new Campaign();  
    c.Region__c = bi.Budget__r.Region__c;
    ///more fields
    ca.add(c);
   }

3

Set<Id> Ids = new Set<Id>();
for(Budget_Item__c c : trigger.new)
    {
        Ids.add(c.Id);
    }

    Map<Id,Budget__c> mapRP = new Map<Id,Budget__c>([SELECT Id, Name, Region__c 
                                                     FROM Budget__c 
                                                     WHERE Id IN:Ids]);
for(Budget_Item__c bi : trigger.new)
   { 
     Campaign c = new Campaign();  
     c.Region__c = bi.Budget__r.Region__c;
     ca.add(c);
   }

What is the preferred method for doing this and which has the least overhead?

2 Answers 2

2

You need to set the Budget__c field value before inserting the Campaign.

I think this can also be simplified to:

List<Campaign> ca = new List <Campaign>();

for(Budget_Item__c bi : [SELECT Id, <etc...> FROM Budget_Item__c WHERE Id IN: Trigger.newMap.keySet()]){
    if(bi.Create_Campaign__c == true){
        Campaign c = new Campaign();
        c.Region__c = bi.Region__c;
        c.Budget__c = bi.Budget__c;
        ca.add(c)
    }
}
4
  • It should already be set though because you cant create a budget item without a budget. So creating a campaign should already have that relationship set up. And i could be having a blonde moment but i guess what im getting to is, how do i set something that is already supposed to be set?
    – Tyler
    Sep 20, 2019 at 16:55
  • I believe you still need to explicitly set the Budget__c field on campaign to the Budget__c field that is on the Budget Item. For example in your first block of code where you are looping through budget items, you would do c.Budget = bi.Budget__c
    – Zach
    Sep 20, 2019 at 17:09
  • 1
    c.Region__c = bi.Region__c; sb c.Region__c = bi.Budget__r.Region__c;
    – cropredy
    Sep 20, 2019 at 20:56
  • You right good catch!
    – Zach
    Sep 20, 2019 at 21:02
2

Edited: You have a trigger on Budget_Item__c records. You need to make sure you can handle the scenario where multiple Budget Items are being updated from different budgets. Even if this is unrealistic, you should at least code to support that scenario.

Likewise, you shouldn't be doing all your logic in the trigger and certainly don't always want to be querying if there's no need to if there's no campaigns that should be created. Naming convention changes as well to avoid confusion with triggers. This would make it easier when you have to add functionality as things are separated and de-coupled. You can add separate logic in the trigger for new scenarios (before triggers) and you can even name your methods in your handler class to be more generic (onInsertMethod()) and then call another class that actually does the insert. Again, this could be overkill at a certain point, but you'd want to not just put all your logic in the trigger at the very least.

In the end, how you do your specific logic (field on parent object) isn't necessarily the most important thing. It's how you structure your logic and code to support maintenance and new features in the future. I'd suggest at least looking at moving your logic away from all being in the trigger at the very least even if you stick with your general logic. trigger Budget_Item_Trigger on Budget_Item__c (after insert, after update) { BudgetItemTriggerHandler budgetItemHandl = new BudgetItemTriggerHandler(); Map budgetItemMapIds= new Map(); if(Trigger.isAfter){ if(Trigger.isUpdate){ for(Budget_Item__c bi : trigger.new){ if(bi.Create_Campaign__c){ budgetItemMapIds.add(bi,bi.Budget__c); } } if(budgetItemIds.size() > 0){ budgetItemHandler.createCampaigns(budgetItemMapIds); } } } public class BudgetItemTriggerHandler { public void createCampaigns(Map budgetItemMapIds){ List campaignList = new List(); Map budgetMap = new Map[SELECT Id,Region__c FROM Budget__c WHERE Id in: budgetItemMapIds.values()]; for(Budget_Item__c bi : budgetItemMapIds.keyset()){ Campaign c = new Campaign(); Id parentBudgetId = budgetItemMapIds.get(bi); c.Region__c = budgetMap.get(parentBudgetId).Region__c; //set other fields campaignList.add(c); } insert campaignList; }

}

10
  • I edited my post hopefully it makes a little more sense now
    – Tyler
    Sep 20, 2019 at 17:05
  • 1
    Zach mentioned it his comment. There seems to be a requirement to set the Budget_Item__c field on the campaign itself since you're starting from a blank campaign record in your code and not setting it. You're essentially creating a campaign with only the Region__c field set. Sep 20, 2019 at 17:12
  • There isn't a budget__c field on Campaign though
    – Tyler
    Sep 20, 2019 at 18:25
  • I missed this the first go around, but is there any reason why you're querying the budget_item__c (Parentdata variable) object when you already have it in the Trigger.new? I assume Parentdata should be a Budget__c object instead as you're trying to get the parent data which you stated Budget was. Sep 20, 2019 at 18:31
  • Because i was getting a null value when trying to access the Region__c field of Budget__c(Parent Object). I tried that first. You have to query for fields that aren't directly on the object your trigger is on.
    – Tyler
    Sep 20, 2019 at 18:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .