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
chaitanya motupalli 13chaitanya motupalli 13 

Trigger to show an error message on Opportunity record

Hi, i have written trigger on opportunity while inset or update. this logic compare opp with already existed prodcuts on org. if it maches we are throughing an error message on opp record. but i am getting null pointer excpetion. please any help

trigger helloOppTrg on Opportunity (after insert,after update) {
    
    list<Id>accIdlst          = new list<Id>();
    list<string>oppOrdernolst = new list<string>();
    for (Opportunity objOpp : Trigger.new) {
        oppOrdernolst.add(objOpp.OrderNumber__c);
        accIdlst.add(objOpp.AccountId);
    }
    system.debug('opp order no entering'+oppOrdernolst);
    system.debug('account id entering'+accIdlst);
    list<Opportunity> oppwithaccount = new list<Opportunity>();
    oppwithaccount = [SELECT Id,AccountId,OrderNumber__c,Account.Name FROM Opportunity WHERE AccountId=:accIdlst];
    list<string>accname= new list<string>();
    for(Opportunity acc:oppwithaccount){
        accname.add(acc.Account.Name);
    }
    system.debug('account name'+accname);
    list<Product2> matchProduct = new list<Product2>();
    matchProduct = [SELECT Id, IsActive, ProductCode, Name FROM Product2
                    WHERE ProductCode =:oppOrdernolst AND Name =:accname];
    system.debug('product records'+matchProduct);
    
    for(Opportunity objOpp:oppwithaccount) {
        system.debug('opp id top'+objOpp.id);
     
        for(Product2 proloop : matchProduct) {
            system.debug('inside second loop');
            if(proloop.IsActive==false && proloop.ProductCode==objOpp.OrderNumber__c
               && proloop.Name==objOpp.Account.Name){
                   system.debug('inside third loop');
                   system.debug('opp id'+objOpp.id); // Id value is showing properly
                    Opportunity oppfromtriggernewmap = Trigger.newMap.get(objOpp.id); // but here it reurns null value
                    system.debug('just opp before error msg'+oppfromtriggernewmap); // Null
                   oppfromtriggernewmap.OrderNumber__c.addError('check is false so can not update/insert record MACHED');// Null pointer exception 
               }
        }
    }
    
}
Best Answer chosen by chaitanya motupalli 13
chaitanya motupalli 13chaitanya motupalli 13
Hi Maharajan,

Thanks for reply. your thought worked but i i made change in SOQL from "Trigger.newMap" to "Trigger.new" since i am getting error message saything 'IN operator must be used with an iterable expression' So final answer is 
 
trigger helloOppTrg on Opportunity (after insert,after update) {
    
    list<Id>accIdlst          = new list<Id>();
    list<string>oppOrdernolst = new list<string>();
    for (Opportunity objOpp : Trigger.new) {
        oppOrdernolst.add(objOpp.OrderNumber__c);
		if(objOpp.AccountId != null)   // Add the null check
			accIdlst.add(objOpp.AccountId);
    }
    system.debug('opp order no entering'+oppOrdernolst);
    system.debug('account id entering'+accIdlst);
    list<Opportunity> oppwithaccount = new list<Opportunity>();
	oppwithaccount = [SELECT Id,AccountId,OrderNumber__c,Account.Name FROM Opportunity WHERE AccountId=:accIdlst AND Id IN: Trigger.New];    
	list<string>accname= new list<string>();
    for(Opportunity acc:oppwithaccount){
        accname.add(acc.Account.Name);
    }
    system.debug('account name'+accname);
    list<Product2> matchProduct = new list<Product2>();
    matchProduct = [SELECT Id, IsActive, ProductCode, Name FROM Product2
                    WHERE ProductCode =:oppOrdernolst AND Name =:accname];
    system.debug('product records'+matchProduct);
    
    for(Opportunity objOpp:oppwithaccount) {
        system.debug('opp id top'+objOpp.id);
     
        for(Product2 proloop : matchProduct) {
            system.debug('inside second loop');
            if(proloop.IsActive==false && proloop.ProductCode==objOpp.OrderNumber__c
               && proloop.Name==objOpp.Account.Name){
                   system.debug('inside third loop');
                   system.debug('opp id'+objOpp.id); // Id value is showing properly
				    if(Trigger.newMap.ContainsKey(objOpp.id))  // To Avoid the Null Exception use this check
					{
						Opportunity oppfromtriggernewmap = Trigger.newMap.get(objOpp.id); // but here it reurns null value
						system.debug('just opp before error msg'+oppfromtriggernewmap); // Null
						oppfromtriggernewmap.OrderNumber__c.addError('check is false so can not update/insert record MACHED');// Null pointer exception 
					}
               }
        }
    }
    
}

 

All Answers

Maharajan CMaharajan C
Hi Chaitanya,

if the account has some existing opportunity that also will come in the below query. But it will not present in the Trigger.NewMap(which is the newly created or edited records). So that in the for loop trigger.newmap giving null.
oppwithaccount = [SELECT Id,AccountId,OrderNumber__c,Account.Name FROM Opportunity WHERE AccountId=:accIdlst];

In the above query add one more condition to check the Trigger.New Opps only.
oppwithaccount = [SELECT Id,AccountId,OrderNumber__c,Account.Name FROM Opportunity WHERE AccountId=:accIdlst and Id IN: Trigger.NewMap];

 
trigger helloOppTrg on Opportunity (after insert,after update) {
    
    list<Id>accIdlst          = new list<Id>();
    list<string>oppOrdernolst = new list<string>();
    for (Opportunity objOpp : Trigger.new) {
        oppOrdernolst.add(objOpp.OrderNumber__c);
		if(objOpp.AccountId != null)   // Add the null check
			accIdlst.add(objOpp.AccountId);
    }
    system.debug('opp order no entering'+oppOrdernolst);
    system.debug('account id entering'+accIdlst);
    list<Opportunity> oppwithaccount = new list<Opportunity>();
	oppwithaccount = [SELECT Id,AccountId,OrderNumber__c,Account.Name FROM Opportunity WHERE AccountId=:accIdlst AND Id IN: Trigger.NewMap];    
	list<string>accname= new list<string>();
    for(Opportunity acc:oppwithaccount){
        accname.add(acc.Account.Name);
    }
    system.debug('account name'+accname);
    list<Product2> matchProduct = new list<Product2>();
    matchProduct = [SELECT Id, IsActive, ProductCode, Name FROM Product2
                    WHERE ProductCode =:oppOrdernolst AND Name =:accname];
    system.debug('product records'+matchProduct);
    
    for(Opportunity objOpp:oppwithaccount) {
        system.debug('opp id top'+objOpp.id);
     
        for(Product2 proloop : matchProduct) {
            system.debug('inside second loop');
            if(proloop.IsActive==false && proloop.ProductCode==objOpp.OrderNumber__c
               && proloop.Name==objOpp.Account.Name){
                   system.debug('inside third loop');
                   system.debug('opp id'+objOpp.id); // Id value is showing properly
				    if(Trigger.newMap.ContainsKey(objOpp.id))  // To Avoid the Null Exception use this check
					{
						Opportunity oppfromtriggernewmap = Trigger.newMap.get(objOpp.id); // but here it reurns null value
						system.debug('just opp before error msg'+oppfromtriggernewmap); // Null
						oppfromtriggernewmap.OrderNumber__c.addError('check is false so can not update/insert record MACHED');// Null pointer exception 
					}
               }
        }
    }
    
}

Thanks,
Maharajan.C




 
chaitanya motupalli 13chaitanya motupalli 13
Hi Maharajan,

Thanks for reply. your thought worked but i i made change in SOQL from "Trigger.newMap" to "Trigger.new" since i am getting error message saything 'IN operator must be used with an iterable expression' So final answer is 
 
trigger helloOppTrg on Opportunity (after insert,after update) {
    
    list<Id>accIdlst          = new list<Id>();
    list<string>oppOrdernolst = new list<string>();
    for (Opportunity objOpp : Trigger.new) {
        oppOrdernolst.add(objOpp.OrderNumber__c);
		if(objOpp.AccountId != null)   // Add the null check
			accIdlst.add(objOpp.AccountId);
    }
    system.debug('opp order no entering'+oppOrdernolst);
    system.debug('account id entering'+accIdlst);
    list<Opportunity> oppwithaccount = new list<Opportunity>();
	oppwithaccount = [SELECT Id,AccountId,OrderNumber__c,Account.Name FROM Opportunity WHERE AccountId=:accIdlst AND Id IN: Trigger.New];    
	list<string>accname= new list<string>();
    for(Opportunity acc:oppwithaccount){
        accname.add(acc.Account.Name);
    }
    system.debug('account name'+accname);
    list<Product2> matchProduct = new list<Product2>();
    matchProduct = [SELECT Id, IsActive, ProductCode, Name FROM Product2
                    WHERE ProductCode =:oppOrdernolst AND Name =:accname];
    system.debug('product records'+matchProduct);
    
    for(Opportunity objOpp:oppwithaccount) {
        system.debug('opp id top'+objOpp.id);
     
        for(Product2 proloop : matchProduct) {
            system.debug('inside second loop');
            if(proloop.IsActive==false && proloop.ProductCode==objOpp.OrderNumber__c
               && proloop.Name==objOpp.Account.Name){
                   system.debug('inside third loop');
                   system.debug('opp id'+objOpp.id); // Id value is showing properly
				    if(Trigger.newMap.ContainsKey(objOpp.id))  // To Avoid the Null Exception use this check
					{
						Opportunity oppfromtriggernewmap = Trigger.newMap.get(objOpp.id); // but here it reurns null value
						system.debug('just opp before error msg'+oppfromtriggernewmap); // Null
						oppfromtriggernewmap.OrderNumber__c.addError('check is false so can not update/insert record MACHED');// Null pointer exception 
					}
               }
        }
    }
    
}

 
This was selected as the best answer
Abdul KhatriAbdul Khatri
Hi Chaitanya

First of all Thanks Maharajan, for helping out.

The following question is for both of you. Anyone can help reply.

I am little confuse with the code as it is written and what you are asking, I think it can be simplified, may be I am missing something.
  • Looks like your end goal is to look at the flag IsActive of that product for which opportunity OrderNumber (ProdcutCode) is either getting inserted or updated?
  • Isn't the trigger should be either on before update or before insert becuase after insert and after update means, it is done?
Will appreciate your reply so I understand for my knowledge
chaitanya motupalli 13chaitanya motupalli 13
Hi Abdul

1)Yes you are right
2)We are using Opportunity Id in this trigger so we must user after. If you use before system dont generate Opportunity Id. 
Note: though system gerenate opportunity ID in the process it wont get saved into system permanently unless trigger runs properly with out any error messsages.
Abdul KhatriAbdul Khatri
Hi Chaitanya,

I know that but your following message is referencing which record? I think Opportunity, if that is the case the record is already updated or inserted, it didn't get in align with the message, how you prevented that to happen.

check is false so can not update/insert record MACHED
Abdul KhatriAbdul Khatri
Hi Chaitanya / Maharajan

Any thoughts?