function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
JustinWilliams2381JustinWilliams2381 

So close with this code but have 2 issues

The purpose of this trigger is to take a closed won opportunity that is of a certain picklist option 'Subscription_Type__c = 'GradeBeam' and clone it along with the primary contact if there is one.  The reeason is that when we sell a subscription we want to create a renewal oppotunity 1,2, or 3 years down the road.  I have two issues with this code otherwise it works:

 

1. When I close an opportunity it creates 2 clones instead of 1.

2. I have to have a product on the opp before I close otherwise I get "Attempt to de-refference a null object" which is a problem because certain opportunities won't use products, just those who's subscription type is 'GradeBeam'.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
trigger RenewalOppCreate on Opportunity (After update) {
    
  try {

        // List of opportunity IDs
      ID OppId ;
        
        for( opportunity opp: Trigger.New){
        if ((opp.StageName == 'Closed Won') && (opp.Subscription_Type__c == 'GradeBeam')&& (trigger.oldMap.get(opp.id).StageName != 'Closed Won' )){
            OppId = opp.Id;
        }
        }

        
    for( opportunity oldOpp: [SELECT ID, accountId, account.name, Estimated_Renewal_Date__c FROM opportunity WHERE Id = :OppId]){
        
        opportunity renewOpp = New opportunity();
            renewOpp.closedate = oldOpp.Estimated_Renewal_Date__c;
            renewOpp.AccountId = oldOpp.accountId;
            renewOpp.name = oldOpp.account.name + ' Renewal';
            renewOpp.stagename = 'Renewal Scheduled';
            renewOpp.Type = 'Repeat Client';
            insert renewOpp;
            
        
            for( OpportunityContactRole Role: [SELECT ID, ContactId, Role FROM opportunityContactRole WHERE IsPrimary = TRUE AND opportunityId = :OldOpp.ID]){
        
        opportunityContactRole ContactRole = New opportunityContactRole();
            ContactRole.ContactId = Role.ContactId;
            ContactRole.OpportunityId = renewOpp.Id;
            ContactRole.IsPrimary = true;
     
            insert ContactRole;
        }
        }
        
    }catch (Exception e) {Trigger.new[0].addError(e.getMessage());}
}

Best Answer chosen by Admin (Salesforce Developers) 
Andrew WilkinsonAndrew Wilkinson

So there are a couple things with your code. With this you will probably hit governor limits as well. I revised your code. Try this instead.

 

      try {

        // List of opportunity IDs
      Set<Id> oppIds = new Set<Id>();
      //lists used for bulk
      List<Opportunity> clonesToInsert = new List<Opportunity>();
      

        
        for( opportunity opp: Trigger.New){
        if ((opp.StageName == 'Closed Won') && (opp.Subscription_Type__c == 'GradeBeam')&& (trigger.oldMap.get(opp.id).StageName != 'Closed Won' )){
            oppIds.add(o.Id);
        }
        }

       
    for( opportunity oldOpp: [SELECT ID, accountId, account.name, Estimated_Renewal_Date__c FROM opportunity WHERE Id IN :OppIds]){
        
        opportunity renewOpp = New opportunity();
            renewOpp.closedate = oldOpp.Estimated_Renewal_Date__c;
            renewOpp.AccountId = oldOpp.accountId;
            renewOpp.name = oldOpp.account.name + ' Renewal';
            renewOpp.stagename = 'Renewal Scheduled';
            renewOpp.Type = 'Repeat Client';
            clonesToInsert.add(renewOpp);
    }  
    List<OpportunityContactRole> roles = new List<OpportunityContactRole>();
    for( OpportunityContactRole Role: [SELECT ID, ContactId, Role,Role.ContactId FROM opportunityContactRole WHERE IsPrimary = TRUE AND opportunityId IN :OppIds]){
        
        opportunityContactRole ContactRole = New opportunityContactRole();
            ContactRole.ContactId = Role.ContactId;
            ContactRole.OpportunityId = renewOpp.Id;
            ContactRole.IsPrimary = true;
     
            roles.add(ContactRole);
     }
     insert clonesToInsert;
     insert roles;
        
    }catch (Exception e) {Trigger.new[0].addError(e.getMessage());}

 Now from here since this will handle bulk loads and won't hit governor limits try to run this and see if it resolves your issues.

All Answers

Andrew WilkinsonAndrew Wilkinson

So there are a couple things with your code. With this you will probably hit governor limits as well. I revised your code. Try this instead.

 

      try {

        // List of opportunity IDs
      Set<Id> oppIds = new Set<Id>();
      //lists used for bulk
      List<Opportunity> clonesToInsert = new List<Opportunity>();
      

        
        for( opportunity opp: Trigger.New){
        if ((opp.StageName == 'Closed Won') && (opp.Subscription_Type__c == 'GradeBeam')&& (trigger.oldMap.get(opp.id).StageName != 'Closed Won' )){
            oppIds.add(o.Id);
        }
        }

       
    for( opportunity oldOpp: [SELECT ID, accountId, account.name, Estimated_Renewal_Date__c FROM opportunity WHERE Id IN :OppIds]){
        
        opportunity renewOpp = New opportunity();
            renewOpp.closedate = oldOpp.Estimated_Renewal_Date__c;
            renewOpp.AccountId = oldOpp.accountId;
            renewOpp.name = oldOpp.account.name + ' Renewal';
            renewOpp.stagename = 'Renewal Scheduled';
            renewOpp.Type = 'Repeat Client';
            clonesToInsert.add(renewOpp);
    }  
    List<OpportunityContactRole> roles = new List<OpportunityContactRole>();
    for( OpportunityContactRole Role: [SELECT ID, ContactId, Role,Role.ContactId FROM opportunityContactRole WHERE IsPrimary = TRUE AND opportunityId IN :OppIds]){
        
        opportunityContactRole ContactRole = New opportunityContactRole();
            ContactRole.ContactId = Role.ContactId;
            ContactRole.OpportunityId = renewOpp.Id;
            ContactRole.IsPrimary = true;
     
            roles.add(ContactRole);
     }
     insert clonesToInsert;
     insert roles;
        
    }catch (Exception e) {Trigger.new[0].addError(e.getMessage());}

 Now from here since this will handle bulk loads and won't hit governor limits try to run this and see if it resolves your issues.

This was selected as the best answer
JustinWilliams2381JustinWilliams2381

I had to make a few small changes to satisfy the syntax errors.  It finally stopped making duplicate clones and I figured out the de-reference a null object meant the Amount field had to have a value.  Now off to figuring out test code.  Thanks a buch.

 

By the way.  Why is it  Before Insert instead of Before Update?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
trigger CloneGBOpp on Opportunity (before insert) {
      try {

        // List of opportunity IDs
      Set<Id> oppIds = new Set<Id>();
      //lists used for bulk
      List<Opportunity> clonesToInsert = new List<Opportunity>();
      

        
        for( opportunity opp: Trigger.New){
        if ((opp.StageName == 'Closed Won') && (opp.Subscription_Type__c == 'GradeBeam')&& (trigger.oldMap.get(opp.id).StageName != 'Closed Won' )){
            oppIds.add(opp.Id);
        }
        }

       
    for( opportunity oldOpp: [SELECT ID, accountId, account.name, Estimated_Renewal_Date__c FROM opportunity WHERE Id IN :OppIds]){
        
        opportunity renewOpp = New opportunity();
            renewOpp.closedate = oldOpp.Estimated_Renewal_Date__c;
            renewOpp.AccountId = oldOpp.accountId;
            renewOpp.name = oldOpp.account.name + ' Renewal';
            renewOpp.stagename = 'Renewal Scheduled';
            renewOpp.Type = 'Repeat Client';
            clonesToInsert.add(renewOpp);
      
    List<OpportunityContactRole> roles = new List<OpportunityContactRole>();
    for( OpportunityContactRole Role: [SELECT ID, ContactId, Role FROM opportunityContactRole WHERE IsPrimary = TRUE AND opportunityId IN :OppIds]){
        
        opportunityContactRole ContactRole = New opportunityContactRole();
            ContactRole.ContactId = Role.ContactId;
            ContactRole.OpportunityId = renewOpp.Id;
            ContactRole.IsPrimary = true;
     
            roles.add(ContactRole);
            
     }
           insert roles;
     }
     insert clonesToInsert;

        
    }catch (Exception e) {Trigger.new[0].addError(e.getMessage());}
}