You need to sign in to do that
Don't have an account?
Trigger bulkification issue for create multiple child records
Hi All,
I am facing bulkification issue on creating multiple child records from insert multiple parent record using data loader. It's showing "10:53:29:088 FATAL_ERROR System.LimitException: Too many DML rows: 10001".
Please help me for fixing the issue.
trigger OppTrigger on Opportunity (after insert, after update, before delete) {
// Record Insert Code
if(trigger.isInsert || trigger.isundelete){
if(checkRecursive.runOnce()){
Set<Id> oppId = new Set<Id>();
Map<Id,Opportunity> oppmap = new Map<Id,Opportunity>();
for(Opportunity opp: Trigger.new){
oppId.add(opp.Id);
}
List<Projected_Opportunity__c> proOppList = new List<Projected_Opportunity__c>();
for(Opportunity opps: [SELECT ID,Name,StageName,Probability,
CloseDate,Month_No__c,Implementation_Date__c,
Contract_Term__c,Amount,Projected_Revenue_1__c,
Q1RF_target__c,Total_Project_Revenue__c FROM Opportunity WHERE ID IN:oppId]){
for(Integer i=0; i< Integer.valueOf(opps.Contract_Term__c); i++){
Projected_Opportunity__c po = new Projected_Opportunity__c();
po.Opportunity__c = opps.Id;
po.Opportunity_Name__c = opps.Name;
po.Stage__c = opps.StageName;
po.Probability__c = opps.Probability;
po.Closed_Date__c = opps.CloseDate;
po.Month_No__c = opps.Month_No__c;
po.Projected_Implementation_Date__c = opps.Implementation_Date__c.addMonths(i);
po.Contract_Term__c=opps.Contract_Term__c;
po.Amount__c = opps.Amount;
po.Monthly_Projected_Revenue__c = opps.Projected_Revenue_1__c;
po.Target_Revenue__c = opps.Q1RF_target__c;
po.Total_Project_Revenue__c = opps.Total_Project_Revenue__c;
proOppList.add(po);
}
}
if(!proOppList.isEmpty()){
insert proOppList;
}
/* List<Projected_Opportunity__c> polistInsertRecords = new List<Projected_Opportunity__c>();
for(Opportunity opps: Trigger.new){
for(Integer i=0; i< Integer.valueOf(opps.Contract_Term__c); i++){
Projected_Opportunity__c po = new Projected_Opportunity__c();
po.Opportunity__c = opps.Id;
po.Opportunity_Name__c = opps.Name;
po.Stage__c = opps.StageName;
po.Probability__c = opps.Probability;
po.Closed_Date__c = opps.CloseDate;
po.Month_No__c = opps.Month_No__c;
po.Projected_Implementation_Date__c = opps.Implementation_Date__c.addMonths(i);
po.Contract_Term__c=opps.Contract_Term__c;
po.Amount__c = opps.Amount;
po.Monthly_Projected_Revenue__c = opps.Projected_Revenue_1__c;
po.Target_Revenue__c = opps.Q1RF_target__c;
po.Total_Project_Revenue__c = opps.Total_Project_Revenue__c;
polistInsertRecords.add(po);
}
}
system.debug('polistInsertRecords ' + polistInsertRecords);
if(!polistInsertRecords.isEmpty()){
insert polistInsertRecords;
}*/
/*try{
if(polistInsertRecords.size() >0){
insert polistInsertRecords;
system.debug('Record Inserted...');
}
}catch(DmlException e){
system.debug(e.getMessage());
system.debug(e.getLineNumber());
} */
}
}
//Code for update records
if(trigger.isUpdate){
if(checkRecursive.runOnce()){
Set<Id> oppids = new Set<Id>();
List<Projected_Opportunity__c> polistInsertRecords = new List<Projected_Opportunity__c>();
for(Opportunity op : trigger.new){
oppids.add(op.id);
}
List<Projected_Opportunity__c> proOppForDel = new List<Projected_Opportunity__c>([Select Id,Opportunity_Name__c,Amount__c,
Closed_Date__c,Stage__c,Probability__c,
Projected_Implementation_Date__c,Contract_Term__c,
Monthly_Projected_Revenue__c,Target_Revenue__c
From Projected_Opportunity__c
Where Opportunity__c IN:oppids]);
Delete proOppForDel;
for(Opportunity opps : Trigger.new){
for(Integer i=0; i< opps.Contract_Term__c; i++){
Projected_Opportunity__c po = new Projected_Opportunity__c();
po.Opportunity__c = opps.Id;
po.Opportunity_Name__c = opps.Name;
po.Stage__c = opps.StageName;
po.Probability__c = opps.Probability;
po.Closed_Date__c = opps.CloseDate;
po.Month_No__c = opps.Month_No__c;
po.Projected_Implementation_Date__c = opps.Implementation_Date__c.addMonths(i);
po.Contract_Term__c=opps.Contract_Term__c;
po.Amount__c = opps.Amount;
po.Monthly_Projected_Revenue__c = opps.Projected_Revenue_1__c;
po.Target_Revenue__c = opps.Q1RF_target__c;
po.Total_Project_Revenue__c = opps.Total_Project_Revenue__c;
polistInsertRecords.add(po);
}
}system.debug('polistInsertRecords ' + polistInsertRecords);
try{
if(polistInsertRecords.size() >0){
insert polistInsertRecords;
system.debug('Record Inserted...');
}
}catch(DmlException e){
system.debug(e.getMessage());
system.debug(e.getLineNumber());
}
}
}
}
<pre>
trigger OppTrigger on Opportunity ( after insert, after update, after undelete )
{
if ( ! CheckRecursive.runOnce() ) return;
Set<Id> oppIds = new Set<Id>();
Integer numProOpps = 0;
for ( Opportunity opps : Trigger.new )
{
oppIds.add( opps.Id );
numProOpps += Integer.valueOf( opps.Contract_Term__c );
if ( numProOpps >= 2000 ) // adjust this number to your liking
{
OppTriggerUtils.replaceProjectedOpportunities( oppIds );
oppIds.clear();
numProOpps = 0;
}
}
if ( !oppIds.isEmpty() )
{
OppTriggerUtils.replaceProjectedOpportunities( oppIds );
}
}
public class OppTriggerUtils
{
@future
public static void replaceProjectedOpportunities( Set<Id> oppIds )
{
// this will not error if there are no records to delete
delete [SELECT Id FROM Projected_Opportunity__c WHERE Opportunity__c IN :oppIds];
List<Projected_Opportunity__c> proOppList = new List<Projected_Opportunity__c>();
for ( Opportunity opps :
[ SELECT Id, Name, StageName, Probability, CloseDate, Month_No__c,
Implementation_Date__c, Contract_Term__c, Amount,
Projected_Revenue_1__c, Q1RF_target__c, Total_Project_Revenue__c
FROM Opportunity
WHERE Id IN :oppIds
]
)
{
for ( Integer i = 0; i < Integer.valueOf( opps.Contract_Term__c ); i++ )
{
proOppList.add
( new Projected_Opportunity__c
( Opportunity__c = opps.Id
, Opportunity_Name__c = opps.Name
, Stage__c = opps.StageName
, Probability__c = opps.Probability
, Closed_Date__c = opps.CloseDate
, Month_No__c = opps.Month_No__c
, Projected_Implementation_Date__c = opps.Implementation_Date__c.addMonths(i)
, Contract_Term__c = opps.Contract_Term__c
, Amount__c = opps.Amount
, Monthly_Projected_Revenue__c = opps.Projected_Revenue_1__c
, Target_Revenue__c = opps.Q1RF_target__c
, Total_Project_Revenue__c = opps.Total_Project_Revenue__c
)
);
}
}
insert proOppList;
}
}
</pre>
Hello Glyn,
Greetings of the day!
Thanks for your response.
I have implemented your logic.But it's working sometimes and sometimes not. And also in the child records, Monthly Projected Revenue __c, and Account__c values are not fetching.
What do you mean by "values are not fetching"? Are they being set to null?
Let me know and I'll try to help you figure out what's going on.
Hello Glyn,
The very first time the records in child object "Projected Opportunity" from opportunity having 2 value in contract term is created, but it's not updating. And also when I am creating new opportunity it's not creating any child records.
If you're sure you DON'T have more than one trigger on Opportunity, let me know that, too.
Hey Glyn,
Greetings of the day!
Sure, I am alway ready to help you.
I have added multiple debug logs in the trigger and the helper class. I found that the actual error is in line no 23 of oppTrigger.
The error is "FATAL_ERROR System.AsyncException: Future method cannot be called from a future or batch method: OppTriggerUtils.replaceProjectedOpportunities(Set<Id>)".
I have tried commenting out the CheckRecursive.runOnce(), but then also the same error occurred.
I have also attached a screenshot for the same.
I'm sorry I can't just tell you what the problem is. You're going to have to do some debugging. Start by trying to determine why it thinks our @future is being called from another @future or batch.
Hello Glyn,
Thanks a lot for all your support!
I have learned so many new logic from the code shared by you.
Actually, there is no other trigger or classes written for that child object and opportunity. And also none of the automation rules were created for the same.
Actually, the issue in bulk data loading. As the governor limit of data loading in Salesforce is 10000, that's why the error has occurred.
Means, I have tried to import 110 opportunities with 99 child object for each opportunity
So the total records is 110 Projected_Opportunities * 99 + 110 Opportunity = 11000. Which cross the SFDC governor limit.
When I tried to import 88 Projected_Opportunities with 110 Opportunities. It's successfully imported.
110 Projected_Opportunities * 88 + 110 Opportunity = 9790. Which comes under the SFDC governor limit.
I request you to plz help me in future also, whenever I need. I'll be always thankful to you for this.
Hello Glyn,
I have a new issue in one of the project.
I have a task assigned to customized the volunteer package and add more filters on it. I have implemented the same. but actually, there is some error in the print view page.
I need to fetch all parent object record based on a filter in the child object.
SOQL:- Select name, (select id,name from GW_Volunteers__Volunteer_Shift__r) from GW_Volunteers__Volunteer_Job__c
Parent: - GW_Volunteers__Volunteer_Job__c
Child:- GW_Volunteers__Volunteer_Shift__r
Error:-
"Didn't understand relationship 'GW_Volunteers__Volunteer_Shift__r' in FROM part of query call. If you are attempting to use a custom relationship, be sure to append the '__r' after the custom relationship name. Please reference your WSDL or the describe call for the appropriate names."
Please help me!
The thing with child relationships is that they're not always named what you think they should be. First, I would try using "GW_Volunteers__Volunteer_Shifts__r" (notice that the plural, "Shifts"). The default child relationship name is always the plural of the child object name. If that doesn't work (or you can do this first), in Setup, go to the GW_Volunteers__Volunteer_Shift__c object definition and click on the field that looks up to GW_Volunteers__Volunteer_Job__c. In the Field Information section, in the right-hand column, is the Child Relationship Name. Use that value (with "__r" appended).
Hey Glyn,
The issue is fixed now. Thanks for your support.
Now I am stuck on a new logic.
I need to set a default picklist value in VF page when it's loading.
What should I do, I don't have any idea.
I have updated the constructor to display the default value but it's not working.
Controller Code: -
global string Shift_Cancellation_Status { get; set; }
// the list of Shift Cancellation Status List
global list<SelectOption> Shiftss_Cancellation_Status_List {
get {
list<SelectOption> listSO =new list<SelectOption>();
//listSO.add(new selectoption('','(all shift cancellation status)'));
listSO.add(new selectoption('all shift cancellation statuses','(all shift cancellation statuses)'));
listSO.add(new selectoption('Canceled by Organization = FALSE','Canceled by Organization = FALSE'));
listSO.add(new selectoption('Canceled by Organization = TRUE','Canceled by Organization = TRUE'));
return listSO;
}
set;
}
VFPAGE code: -
<div class="slds-form-element">
<apex:outputLabel value="Shift Cancellation Status" for="ddlShiftCancellationStatus" styleClass="slds-form-element__label" />
<div class="slds-form-element__control">
<div class="slds-select_container">
<apex:selectList id="ddlShiftCancellationStatus" value="{!Shift_Cancellation_Status}" size="1" styleClass="slds-select" >
<apex:actionSupport immediate="false" event="onchange" rerender="panelPrint"
status="retrieveStatus" action="{!ChangeShiftCancellationStatus}" />
<apex:selectOptions value="{!Shift_Cancellation_Status_List}" />
</apex:selectList>
</div>
</div>
</div>
Plz help me!