• Jeff G
  • NEWBIE
  • 30 Points
  • Member since 2015

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 8
    Questions
  • 6
    Replies
Hi all,

I am writing a trigger which should aggregate the info on all Opportunity Products associated with an Opportunity, and then populate this info onto the Opportunity in the form of checking the relevant checkboxes. Ex: if product A is based in Houston and product B is based in New York, then the checkboxes for both "Houston" and "New York" should be checked on the Opportunity associated with products A and B.

The problem I'm having is that the Opportunity I am referencing through my Opportunity Product appears to be a null object. When I try to set a checkbox value to true, for example, I get the following error:
TestUpdateOppCheckboxes: execution of BeforeUpdate caused by: System.NullPointerException: Attempt to de-reference a null object

Yes, I can check for a null value or surround my code with a try/catch block, and this would avoid the exception, but that is not the point. I would like to know why the Opportunity I am looking up through my Opportunity Product is a null object. Here is a part of my trigger so far:

trigger TestUpdateOppCheckboxes on OpportunityLineItem (before insert, before update) {
     for(OpportunityLineItem OppItemRecord : Trigger.new) {
           Opportunity o = OppItemRecord.Opportunity;

           if(OppItemRecord.Location__c.contains('NY') && !OppItemRecord.Opportunity.NY__c) {
                 o.NY__c = true;     //here the trigger should be checking off the 'NY' checkbox on the opportunity
                                                 //this is where I would get the exception, since I would be trying to derefence 'o', which is null
           }
     }
}

Any suggestions would be great, thanks in advance!

Best,
Jeff
Hi all,

I am trying to update the probability and stage name fields for my Opportunity based on the completion of a custom object 'QQ'. My QQ and Opportunity are in a master-detail relationship, and I've rolled up the QQ total % to the Opportunity object.

To go about this, I've written a trigger that compares the QQ roll up percentage with the Opportunity's probablity percentage. If they are different, I change the Opportunity Probability to that of the QQ percentage, and I adjust the Opportunity's stage field based on certain ranges of percentages. For example, if the QQ is 32-52% complete, I change the Opportunity's stage to 'Solution'.

So long as the QQ Roll Up field populates on the Opportunity layout, this trigger works fine in practice. However, when writing a test class for the trigger, the stage field of my opportunity object never changes from the initial stage I declared it as having. Thus I always get an assertion error: System.AssertException: Assertion Failed: Expected: Solution, Actual: Warm Prospect

My code is shown below:
(1) Trigger
trigger NOVAUpdateOppProb on Opportunity (before update) {

    Map<Id,Decimal>OppRecordMap=new Map<Id,Decimal>();     //To capture the Opp records that had any changes in QQ Rollup

    for(Opportunity OppRecord : Trigger.new) {

       //here I update the Opportunity's stage (if applicable):
        if(OppRecord.QQ_Roll_Up__c == 100) {
                 OppRecord.StageName = 'Closed Won';                       
            }       
            else if(OppRecord.QQ_Roll_Up__c < 0) {
                 OppRecord.StageName = 'Closed Lost';  
            }
                
            else if(OppRecord.QQ_Roll_Up__c < 100) {
                    
                 if(OppRecord.QQ_Roll_Up__c<89) {
                    
                      if(OppRecord.QQ_Roll_Up__c<53) {
                         
                           if(OppRecord.QQ_Roll_Up__c<32) {
                                
                                if(OppRecord.QQ_Roll_Up__c<12) {
                                
                                     if(OppRecord.QQ_Roll_Up__c == 0) {
                                         OppRecord.StageName = 'Warm Prospect';    //if 0%. stage is in Warm Prospect phase
                                     }
                                     else OppRecord.StageName = 'Discovery';    //if 1-11%, stage is in Discovery phase
                                }
                                else OppRecord.StageName = 'Qualify';    //if 12-31%, stage is in Qualify phase
                              }
                              else OppRecord.StageName = 'Solution';    //if 32-52%, stage is in Solution phase
                        }
                      else OppRecord.StageName = 'Close';    //if 53-88%, stage is in Close phase
                 }
                 else OppRecord.StageName = 'Launch';    //if 89-99%, stage is in Launch phase
             }

        // Here I update the Opportunity's probability:
        if((OppRecord.QQ_Roll_Up__c != OppRecord.Probability) && (OppRecord.QQ_Roll_Up__c != Null)) {
            OppRecord.Probability = OppRecord.QQ_Roll_Up__c;
        }   
    }
}

------------------------------------------
(2) Test Class
@isTest
public class TestUpdateProbTrigger {
    static testMethod void insertNewOpp() {
        
       account acct = new account(Name = 'testing');
       insert acct;
        
        
       Opportunity o = new Opportunity(
               Name = 'testing',
               AccountId = acct.id,
               CloseDate = System.today(),
               StageName = 'Warm Prospect'
       );
       
        insert o;
        
        Opportunity oppty = [SELECT id,
                            Name from Opportunity where Id =: o.Id limit 1];
        
        System.assertEquals(o.Name, 'testing');
            QQ__c q = new QQ__c (
                Name = 'test',
                Opportunity_m__c =o.Id,     //"Opportunity_m" refers to the master-detail field on the QQ
                Opportunity__c = o.Id);        //"Opportunity__c" refers to the opportunity look-up field on the QQ
        
        Insert q;
        
        System.assertEquals('Warm Prospect', o.StageName);
        
        q.D1_x__c = true;
        q.D2_x__c = true;
        q.D3_x__c = true;        
        q.D4_x__c = true;
        q.D5_x__c = true;
        q.D6_x__c = true;
        q.D7_x__c = true;
        q.D8_x__c = true;
        
        update q;

       //the following assignments change the QQ's percentage, and I manipulate these to (ideally) change the opportunity's stage
        q.Q1_x__c = true;
        q.Q2_x__c = true;
        q.Q3_x__c = true;
        q.Q4_x__c = true;
        q.Q5_x__c = true;
        q.Q6_x__c = true;
        q.Q7_x__c = true;
        q.Q8_x__c = true;
        q.Q9_x__c = true;
        q.Q10_x__c = true;
        
        update q;
        System.assertEquals('Solution', o.StageName);    //THIS IS WHERE I GET THE ASSERTION ERROR
        
        q.S1_x__c = true;
        q.S2_x__c = true;
        q.S3_x__c = true;
        q.S4_x__c = true;
        q.S5_x__c = true;
        q.S6_x__c = true;
        q.S7_x__c = true;
        q.S8_x__c = true;
        q.S9_x__c = true;
        
        update q;
        System.assertEquals('Close', o.StageName);
        
        q.S9_x__c = false;

         update q;
        System.assertEquals('Solution', o.StageName);
    }
}

I am not sure why the opportunity in the test class is not changing its stage accordingly. Is it because of the master-detail relationship? I did set it to read/write, though.

Any suggestions would be excellent. Thanks in advance!

-Jeff
Hi all,

I want to update the stage of an opportunity based on the completion percentage of a custom 'QQ' object linked to that opportunity.

So far, I have a trigger that automatically updates the standard probability field of the opportunity whenever the QQ is changed.

I have just written another trigger that I want to update the opportunity's stage name: basically, if the standard probability is within a certain range of %, I want the opportunity to be at the corresponding stage 'x'.

It basically consists of a bunch of nested conditionals:

trigger UpdateStage on Opportunity (after update) {
    for(Opportunity p:Trigger.new) {
        
               if(p.Probability  == 100) {
                    p.StageName = 'Closed Won';
                    //problem: in the QQ, there is no % assoc. with step 6 ('Invoiced') of the Launch phase...
                    //total % can be 100% without having fully closed and won the sale                                 
                }
                
                else if(p.Probability < 0) {
                    p.StageName = 'Closed Lost';    //will associate a negative value with a closed lost (to distinguish it from warm prospect)
                }
                
                else if(p.Probability < 100) {
                    
                    if(p.Probability<89) {
                    
                        if(p.Probability<53) {
                         
                            if(p.Probability<32) {
                                
                                if(p.Probability<12) {
                                
                                    if(p.Probability == 0) {
                                        p.StageName = 'Warm Prospect';    //if 0%. stage is in Warm Prospect phase
                                    }
                                    else p.StageName = 'Discovery';    //if 0-12%, stage is in Discovery phase
                                }
                                else p.StageName = 'Qualify';    //if 12-32%, stage is in Qualify phase
                            }
                            else p.StageName = 'Solution';    //if 32-53%, stage is in Solution phase
                        }
                        else p.StageName = 'Close';    //if 53-89%, stage is in Close phase
                    }
                    else p.StageName = 'Launch';    //if 89-100%, stage is in Launch phase
                }
   }
}

The problem is, whenver I activate this updateStage trigger in conjunction with my probability updating trigger, I get the following error:

Apex trigger FINALUpdateOppProb caused an unexpected exception, contact your administrator: UpdateOppProb: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 006G000000Xk7U6IAJ; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, UpdateStage: execution of AfterUpdate caused by: System.FinalException: Record is read-only Trigger.UpdateStage: line 29, column 1: []: Trigger.FINALUpdateOppProb: line 46, column 1

Can I not alter the stage name if it is a read-only record? Does anyone know if there are ways around this?

Thanks in advance!
-Jeff
Hello,

I am trying to write an apex trigger that updates the Probability field of my Opportunity object whenever I change the probability field of a custom object 'QQ'. My Opportunity and QQ have a master-detail relationship.
  
I am new to apex triggers, though intuitively I would write something like this:

trigger TestUpdateProbability on Opportunity (before insert, before update) {
        for(Opportunity p : Trigger.new) {
                p.Probability = p.QQ__r.Total__c;
        }
}

This doesn't seem to be working.
I can't use a workflow either, because the Probability field in an Opportunity object is set according to the Stage field. 
I would like to change the Opportunity probability based on my custom QQ's probability, though that is difficult since each stage is associated with only one preset Probability percentage.

Does anyone know how to get around this? Thanks.