You need to sign in to do that
Don't have an account?
Megan Harris 18
apex help: CPU time limit Error
Hello,
I'm still learning Apex and am having issues this this particular trigger. We want to automate the creation of a renewal opportunity when an opportunity is moved to Closed won.
Requirements
1. Opportunity is Won
2. Create a Renewal Opportunity with a close date of +365 days
3. Clone the primary quotes under the original Opportunity and associate them to the renewal Opportunity
4. Clone the Lines under the Original primary quotes and assoicate them to the cloned "renewal" quotes
Here is my code so far. The error I'm running into is the CPU time limit error, and was gatting the too many SOQL queries earlier. Your help is greatly appreciated!
trigger Renewals2 on Opportunity (before update) {
List <SCMC__Customer_Quotation__c> finalCustomerQuotations = new list <SCMC__Customer_Quotation__c>();
List <SCMC__Customer_Quotation_Line__c> finalCQLines = new list <SCMC__Customer_Quotation_Line__c>();
Map <ID,Opportunity> OrgOpptoRenewOpp = new Map <ID,Opportunity>();
Map <ID,SCMC__Customer_Quotation__c> OrgCQtoRenewCQ = new Map <ID,SCMC__Customer_Quotation__c>();
List <Opportunity> renewalOpps = new list <Opportunity>();
for(Opportunity O : trigger.new){
if (O.StageName == 'Closed - Won'){
//Create a renewal Opportunities
Opportunity newOpp = new Opportunity();
newOpp.name = O.name+'_RENEWAL';
newOpp.Stagename = 'Decision - 60%';
newOpp.CloseDate = O.CloseDate + 365;
newOpp.Description = 'Renewal';
newOpp.OwnerId = O.OwnerId;
newOpp.AccountId = O.AccountId;
renewalOpps.add(newOpp);
Insert renewalOpps;
OrgOpptoRenewOpp.put(O.Id, newOpp);
system.debug('This is the Org Opp id Map to new Opp ' + O.Id +' ' + newOpp);
//Find the primary CQs
List <SCMC__Customer_Quotation__c> OriginalCQs = [SELECT ID,
SCMC__Customer_Account__c,
SCMC__Sales_Rep__c,
SCMC__Opportunity__c
FROM SCMC__Customer_Quotation__c
WHERE SCMC__Opportunity__c = :O.Id
AND Primary__c = true];
System.debug('Number of primary CQs = '+ OriginalCQs.size());
//Find the primary CQLines
List <SCMC__Customer_Quotation_Line__c> OriginalLines = [SELECT ID,
SCMC__Item_Number__c,
SCMC__Quantity__c,
SCMC__Extend_Description__c,
SCMC__Lookup_Manufacturer__c,
SCMC__Customer_Quotation__r.id
FROM SCMC__Customer_Quotation_Line__c
WHERE SCMC__Customer_Quotation__c IN :OriginalCQs];
System.debug('Number of CQLines = ' + OriginalLines.size());
//Clone Quotes and Lines
for(SCMC__Customer_Quotation__c OriginalQuote : OriginalCQs){
SCMC__Customer_Quotation__c renewalCQ = new SCMC__Customer_Quotation__c();
renewalCQ.SCMC__Customer_Account__c = OriginalQuote.SCMC__Customer_Account__c;
renewalCQ.SCMC__Sales_Rep__c = OriginalQuote.SCMC__Sales_Rep__c;
renewalCQ.SCMC__Opportunity__c = OrgOpptoRenewOpp.get(OriginalQuote.SCMC__Opportunity__c).Id;
renewalCQ.Primary__c = TRUE;
renewalCQ.SCMC__Quotation_Expires_On__c = Date.today() + 365;
renewalCQ.RecordTypeId = '012C0000000Qb0x';
finalCustomerQuotations.add(renewalCQ);
OrgCQtoRenewCQ.put(OriginalQuote.Id, renewalCQ);
system.debug('map of ORG CQ to Renewal CQ ' + OriginalQuote.Id + ' ' + renewalCQ);
}
Insert finalCustomerQuotations;
for(SCMC__Customer_Quotation_Line__c OriginalLine : OriginalLines){
SCMC__Customer_Quotation_Line__c renewalLine = new SCMC__Customer_Quotation_Line__c();
renewalLine.SCMC__Item_Number__c = OriginalLine.SCMC__Item_Number__c;
renewalLine.SCMC__Quantity__c = OriginalLine.SCMC__Quantity__c;
renewalLine.SCMC__Extend_Description__c = OriginalLine.SCMC__Extend_Description__c;
renewalLine.SCMC__Lookup_Manufacturer__c = OriginalLine.SCMC__Lookup_Manufacturer__c;
renewalLine.SCMC__Customer_Quotation__c = OrgCQtoRenewCQ.get(OriginalLine.SCMC__Customer_Quotation__c).id;
finalCQLines.add(renewalLine);
}
}
Insert finalCQLines;
system.debug('number of renewal opps created '+ renewalOpps.size());
system.debug('number of renewal CQs created '+ finalCustomerQuotations.size());
system.debug('number of renewal opps created '+ finalCQLines.size());
}
}
I'm still learning Apex and am having issues this this particular trigger. We want to automate the creation of a renewal opportunity when an opportunity is moved to Closed won.
Requirements
1. Opportunity is Won
2. Create a Renewal Opportunity with a close date of +365 days
3. Clone the primary quotes under the original Opportunity and associate them to the renewal Opportunity
4. Clone the Lines under the Original primary quotes and assoicate them to the cloned "renewal" quotes
Here is my code so far. The error I'm running into is the CPU time limit error, and was gatting the too many SOQL queries earlier. Your help is greatly appreciated!
trigger Renewals2 on Opportunity (before update) {
List <SCMC__Customer_Quotation__c> finalCustomerQuotations = new list <SCMC__Customer_Quotation__c>();
List <SCMC__Customer_Quotation_Line__c> finalCQLines = new list <SCMC__Customer_Quotation_Line__c>();
Map <ID,Opportunity> OrgOpptoRenewOpp = new Map <ID,Opportunity>();
Map <ID,SCMC__Customer_Quotation__c> OrgCQtoRenewCQ = new Map <ID,SCMC__Customer_Quotation__c>();
List <Opportunity> renewalOpps = new list <Opportunity>();
for(Opportunity O : trigger.new){
if (O.StageName == 'Closed - Won'){
//Create a renewal Opportunities
Opportunity newOpp = new Opportunity();
newOpp.name = O.name+'_RENEWAL';
newOpp.Stagename = 'Decision - 60%';
newOpp.CloseDate = O.CloseDate + 365;
newOpp.Description = 'Renewal';
newOpp.OwnerId = O.OwnerId;
newOpp.AccountId = O.AccountId;
renewalOpps.add(newOpp);
Insert renewalOpps;
OrgOpptoRenewOpp.put(O.Id, newOpp);
system.debug('This is the Org Opp id Map to new Opp ' + O.Id +' ' + newOpp);
//Find the primary CQs
List <SCMC__Customer_Quotation__c> OriginalCQs = [SELECT ID,
SCMC__Customer_Account__c,
SCMC__Sales_Rep__c,
SCMC__Opportunity__c
FROM SCMC__Customer_Quotation__c
WHERE SCMC__Opportunity__c = :O.Id
AND Primary__c = true];
System.debug('Number of primary CQs = '+ OriginalCQs.size());
//Find the primary CQLines
List <SCMC__Customer_Quotation_Line__c> OriginalLines = [SELECT ID,
SCMC__Item_Number__c,
SCMC__Quantity__c,
SCMC__Extend_Description__c,
SCMC__Lookup_Manufacturer__c,
SCMC__Customer_Quotation__r.id
FROM SCMC__Customer_Quotation_Line__c
WHERE SCMC__Customer_Quotation__c IN :OriginalCQs];
System.debug('Number of CQLines = ' + OriginalLines.size());
//Clone Quotes and Lines
for(SCMC__Customer_Quotation__c OriginalQuote : OriginalCQs){
SCMC__Customer_Quotation__c renewalCQ = new SCMC__Customer_Quotation__c();
renewalCQ.SCMC__Customer_Account__c = OriginalQuote.SCMC__Customer_Account__c;
renewalCQ.SCMC__Sales_Rep__c = OriginalQuote.SCMC__Sales_Rep__c;
renewalCQ.SCMC__Opportunity__c = OrgOpptoRenewOpp.get(OriginalQuote.SCMC__Opportunity__c).Id;
renewalCQ.Primary__c = TRUE;
renewalCQ.SCMC__Quotation_Expires_On__c = Date.today() + 365;
renewalCQ.RecordTypeId = '012C0000000Qb0x';
finalCustomerQuotations.add(renewalCQ);
OrgCQtoRenewCQ.put(OriginalQuote.Id, renewalCQ);
system.debug('map of ORG CQ to Renewal CQ ' + OriginalQuote.Id + ' ' + renewalCQ);
}
Insert finalCustomerQuotations;
for(SCMC__Customer_Quotation_Line__c OriginalLine : OriginalLines){
SCMC__Customer_Quotation_Line__c renewalLine = new SCMC__Customer_Quotation_Line__c();
renewalLine.SCMC__Item_Number__c = OriginalLine.SCMC__Item_Number__c;
renewalLine.SCMC__Quantity__c = OriginalLine.SCMC__Quantity__c;
renewalLine.SCMC__Extend_Description__c = OriginalLine.SCMC__Extend_Description__c;
renewalLine.SCMC__Lookup_Manufacturer__c = OriginalLine.SCMC__Lookup_Manufacturer__c;
renewalLine.SCMC__Customer_Quotation__c = OrgCQtoRenewCQ.get(OriginalLine.SCMC__Customer_Quotation__c).id;
finalCQLines.add(renewalLine);
}
}
Insert finalCQLines;
system.debug('number of renewal opps created '+ renewalOpps.size());
system.debug('number of renewal CQs created '+ finalCustomerQuotations.size());
system.debug('number of renewal opps created '+ finalCQLines.size());
}
}
Another thing is that I'm assuming you want to do this stuff only when the StageName is changed to Closed - Won. Right now this logic will fire any time anyone updates an Opp that has StageName 'Closed - Won', whether the StageName was changed or not. You probably want to include a check to make sure it was actually changed from some other value by getting the previous values from Trigger.old.
Those are the things that stick out to me after initial review.
Let us know if this will help you
The 2 lines in bold and underline are the ones they say are throwing hte null pointer error...any ideas on how to best dereference the null object there?
Thanks for all your help!
if(OriginalCQs.size()>0 ){
for(SCMC__Customer_Quotation__c OriginalQuote : OriginalCQs){
if(OriginalQuote.SCMC__Opportunity__c != null){
SCMC__Customer_Quotation__c renewalCQ = new SCMC__Customer_Quotation__c();
renewalCQ.SCMC__Customer_Account__c = OriginalQuote.SCMC__Customer_Account__c;
renewalCQ.SCMC__Sales_Rep__c = OriginalQuote.SCMC__Sales_Rep__c;
renewalCQ.SCMC__Opportunity__c = oppToRenewal.get(OriginalQuote.SCMC__Opportunity__c).Id;
renewalCQ.Primary__c = TRUE;
renewalCQ.SCMC__Quotation_Expires_On__c = Date.today() + 365;
renewalCQ.RecordTypeId = '012C0000000Qb0x';
renewalCQs.add(renewalCQ);
cqToRenewalCQ.put(OriginalQuote.id, renewalCQ);}
}}
if(renewalCQs.size()>0 && renewalCQs != null){
Insert renewalCQs;
system.debug('Number of renewal CQs created = '+ renewalCQs.size());
Let us know if this will help you
The first line: If there's no value stored in the "oppToRenewal" map for the key "OriginalQuote.SCMC__Opportunity__c" then you'll get null back. If you try to access ".Id" on null - NullPointerException.
The second line: Seems odd that would be giving you an NPE since you're checking to make sure "renewalCQs" isn't null right before. Having said that, the way your "if" conditional is written the "renewalCQs.size() > 0" part will be evaluated before the "renewalCQs != null" part (left to right in this case), so if renewalCQs is null then you'll get an NPE there (calling the "size" method on a null reference).