You need to sign in to do that
Don't have an account?
Second upsert statement within same Apex transaction does not fire trigger
Good morning everyone! Since one cannot create a lookup field to the standard OpportunityLineItem object, you cannot create a parent child relationship between OLIs as you cannot create a lookup to itself. I am mimicking this relationship by using wrapper classes and setting a text(18) custom field called Parent_OLI_Id__c on the OLI. Naturally, I have to save the parents first to get back their IDs, then save the children using the returned IDs. The following method accomplishes this beautifully...
public static void upsertOLIsFromOLIMs(OpportunityLineItemModel[] olims)
{
OpportunityLineItem[] oliParentsToUpsert = new OpportunityLineItem[0];
//Loop thru incoming OLIMs and extract parents only to upsert array
for(OpportunityLineItemModel olim : olims)
{
if(olim.isParent)
oliParentsToUpsert.add(olim.record);
}
try
{
//Upsert parents
upsert oliParentsToUpsert;
//Loop thru incoming OLIMs again and set parent Id of child records
//which has now been returned from previous upsert call
//Extract children to upsert array
OpportunityLineItem[] oliChildrenToUpsert = new OpportunityLineItem[0];
for(OpportunityLineItemModel olim : olims)
{
if(olim.isParent)
{
for(OpportunityLineItemModel childOLIM : olim.childRecords)
{
childOLIM.record.Parent_OLI_Id__c = olim.record.Id;
oliChildrenToUpsert.add(childOLIM.record);
}
}
}
//Upsert children
upsert oliChildrenToUpsert;
}
catch(DmlException dmle)
{
...
}
}
This method is called from a Save button on a VisualForce page. Enough background, now let's get to the problem. I have a trigger that runs after insert and after update of OLIs but is only firing on the first upsert statement of the method above, when upserting the parents. To prevent infinite recursion I am using the usual trick of setting a static Boolean to true the first time the trigger is run. While grasping at straws, I thought this might be causing the problem so I removed the static Boolean condition and let the trigger run ad infinitum. Every single System.debug statement outputted still showed that only parent OLIs were ever being passed to the trigger. Has anyone seen anything like this? I hope it's just because it's late and I'm doing something wrong...
I figured it out; of course I was doing something wrong and went looking for the solution in the wrong place. It was my trigger that was wrong, not the code I posted. Originally, the trigger called one method which used one static Boolean to break out of infinite recursion. The solution was to check to see if the current batch of OLIs were parents or children, then call one of two methods that each had its own static Boolean as below...
trigger OpportunityLineItemAIAUADAR on OpportunityLineItem (after delete, after insert, after undelete, after update)
{
if(Trigger.isInsert || Trigger.isUpdate)
{
if(Trigger.size > 0)
{
if(Trigger.new[0].Parent_OLI_Id__c == 'PARENT' || Trigger.new[0].Parent_OLI_Id__c == 'STANDALONE')
OpportunityLineItemModel.upsertWOPsFromParentOLIs(Trigger.new);
else
OpportunityLineItemModel.upsertWOPsFromChildOLIs(Trigger.new);
}
}
else if(Trigger.isDelete)
OpportunityLineItemModel.deleteWOPsFromOLIs(Trigger.old);
}
public static void upsertWOPsFromParentOLIs(OpportunityLineItem[] olis)
{
if(!OpportunityLineItemModel.didParentTriggerRun)
{
OpportunityLineItemModel.didParentTriggerRun = true;
OpportunityLineItemModel.upsertWOPsFromOLIs(olis);
}
}
public static void upsertWOPsFromChildOLIs(OpportunityLineItem[] olis)
{
if(!OpportunityLineItemModel.didChildTriggerRun)
{
OpportunityLineItemModel.didChildTriggerRun = true;
OpportunityLineItemModel.upsertWOPsFromOLIs(olis);
}
}
All Answers
This line OpportunityLineItem[] oliChildrenToUpsert = new OpportunityLineItem[0]; doesn't it set the array to just 1? you only get array index of 1 always. For ur example it has to keep increasing
- RK
Thanks RK for your assistance! Unfortunately your suggestion is incorrect because the code I posted is working fine; the children are upserted correctly. It's the fact that the trigger doesn't fire when upserting the children that is the problem. The line you refer to uses array notation instead of list notation.
OpportunityLineItem[] oliChildrenToUpsert = new OpportunityLineItem[0];
... is equivalent to...
List<OpportunityLineItem> oliChildrenToUpsert = new List<OpportunityLineItem>();
See Apex docs here regarding array notation.
I figured it out; of course I was doing something wrong and went looking for the solution in the wrong place. It was my trigger that was wrong, not the code I posted. Originally, the trigger called one method which used one static Boolean to break out of infinite recursion. The solution was to check to see if the current batch of OLIs were parents or children, then call one of two methods that each had its own static Boolean as below...
trigger OpportunityLineItemAIAUADAR on OpportunityLineItem (after delete, after insert, after undelete, after update)
{
if(Trigger.isInsert || Trigger.isUpdate)
{
if(Trigger.size > 0)
{
if(Trigger.new[0].Parent_OLI_Id__c == 'PARENT' || Trigger.new[0].Parent_OLI_Id__c == 'STANDALONE')
OpportunityLineItemModel.upsertWOPsFromParentOLIs(Trigger.new);
else
OpportunityLineItemModel.upsertWOPsFromChildOLIs(Trigger.new);
}
}
else if(Trigger.isDelete)
OpportunityLineItemModel.deleteWOPsFromOLIs(Trigger.old);
}
public static void upsertWOPsFromParentOLIs(OpportunityLineItem[] olis)
{
if(!OpportunityLineItemModel.didParentTriggerRun)
{
OpportunityLineItemModel.didParentTriggerRun = true;
OpportunityLineItemModel.upsertWOPsFromOLIs(olis);
}
}
public static void upsertWOPsFromChildOLIs(OpportunityLineItem[] olis)
{
if(!OpportunityLineItemModel.didChildTriggerRun)
{
OpportunityLineItemModel.didChildTriggerRun = true;
OpportunityLineItemModel.upsertWOPsFromOLIs(olis);
}
}