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 

Attempt to de-refference a null object error

Trying to figure out why I'm getting a Error:Attempt to de-reference a null object on this code.  I swear it worked Friday and now it doesn't.

 

 

 

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
trigger RenewalOppCreate on Opportunity (Before update) {
    
  try {

        // List of opportunity IDs
      List<Id> OppId = new List<Id>();
        
        for( opportunity opp: Trigger.New) {
        if ((opp.StageName == 'Closed Won') && (opp.Subscription_Type__c == 'GradeBeam')){
            OppId.add(opp.Id);
        }
    }

        
    for (opportunity oldOpp:[SELECT ID, accountId, account.name, closedate FROM opportunity WHERE Id in :OppId]){
        
        opportunity renewOpp = New opportunity();
            renewOpp.closedate = oldOpp.closedate+365;
            renewOpp.AccountId = oldOpp.accountId;
            renewOpp.name = oldOpp.account.name + ' Renewal';
            renewOpp.stagename = '1. Prospecting';
            renewOpp.Type = 'Repeat Client';
            insert renewOpp;
            }
        
    }catch (Exception e) {Trigger.new[0].addError(e.getMessage());}
}

SFAdmin5SFAdmin5

this trigger works for me in a dev environment

JustinWilliams2381JustinWilliams2381

When one opportunity is marked closed won (and another picklist field = 'GradeBeam') then I want another opportunity to be crated for that same account to represent the next years renewal.

Jia HuJia Hu
Your code works for me too.
Could you give more specific info.?
JustinWilliams2381JustinWilliams2381

Here are the rules I want to follow:

 

When StageName = ClosedWon and Custom Field called 'Subscription Type' = GradeBeam I want to create a new opportunity to represent the current deal's renewal a year down the road.

 

We sell a subscription to a network of contacts.  They run 1, 2, or 3 years in lenght.  To handle renewals in the future I want to have a renewal opportunity created automatically when any GradeBeam subscription is sold.  This is early code where I set the close date of the newly created opp to be a year after the close date of the opp that set off the trigger.  I will also assign it to a specific person, mark it as 'Repeat Client' type.  There may be some more values I will add to pre-fill in this new renewal opp but for now that's it.  I just added a formula field that will be used to set the close date instead of taking the date and making it 365 days from today but that's not in the code yet.

 

I don't think I want to try and clone the product too because a year from now the prices will most likely be different with a different price book.

SFAdmin5SFAdmin5

actually this code does fire but it's got a problem.  every time i edit the original opp it creates another new opp.  so everytime the original opp is edited a new opp is created by this trigger

 

 

JustinWilliams2381JustinWilliams2381

Ah, that explains one of my problems.  I have another trigger in my org someone else wrote to mimic the (when edited and previousely did not meet the criteria) style of workflow.  I can try and incorporate that.  

 

I really want to get fluent with this as well as Visualforce.  I'm at the point I can understand other people's code to copy chunks of it and plug them together.  

JustinWilliams2381JustinWilliams2381

Yeah, now it works for me.  WTF?  Anyway I added a bit of code I found in another trigger to only fire when the stage name was not closed won before.

 

However now it creates two renewal opps for me instead of one.

 

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
trigger RenewalOppCreate on Opportunity (Before update) {
    
  try {

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

        
    for (opportunity oldOpp:[SELECT ID, accountId, account.name, closedate FROM opportunity WHERE Id in :OppId]){
        
        opportunity renewOpp = New opportunity();
            renewOpp.closedate = oldOpp.closedate+365;
            renewOpp.AccountId = oldOpp.accountId;
            renewOpp.name = oldOpp.account.name + ' Renewal';
            renewOpp.stagename = '1. Prospecting';
            renewOpp.Type = 'Repeat Client';
            insert renewOpp;
            }
        
    }catch (Exception e) {Trigger.new[0].addError(e.getMessage());}
}

This code creates 2 identical renewal opps instead of one.  Do I really need to go through all those early steps to capture the Closed Won opp info to apply to the clone or is there simpler code I could use?  I think lines 8,9, and 10 grab two id's in it's list which is why two renewal opps are created but that's a guess.

JustinWilliams2381JustinWilliams2381

Whatever, now it's only creating one renewal opp instead of two and I can't think of why.  Oh well, guess I should just roll with it.  Now I got to figure out how to write test code.  : )