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
Vikas Kumar 135Vikas Kumar 135 

After Delete Trigger now working getting the error "AfterDelete caused by: System.NullPointerException: Attempt to de-reference a null object:"

Hi All,

I wrote to code to trigger to calculate the total opportunity amount on Account but the trigger is not working for After Insert event. It throwing the below error. 

"AfterDelete caused by: System.NullPointerException: Attempt to de-reference a null object:"

Here is my trigger:

trigger Opportunity_AIUD on Opportunity (after insert, after update, after delete) {
    Map<Id, List<Opportunity>> acctIdOpptyListMap = new Map<Id, List<Opportunity>>();
    Map<Id, Opportunity> OldList = new Map<Id, Opportunity>();
    Set<Id> acctIds = new Set<Id>();
    List<Opportunity> opptyList = new List<Opportunity>();
    if(trigger.isUpdate || trigger.isInsert){
        for(Opportunity oppty : trigger.New){
            if(oppty.AccountId != null){
                acctIds.add(oppty.AccountId);
            }
        }    
    }
    
    If(trigger.isafter){
    if(trigger.isDelete){
        for(Opportunity oppty : trigger.old){
            if(oppty.AccountId != null){
                acctIds.add(oppty.AccountId);
                system.debug('*******acctIds*******'+acctIds);
             
            }
        }    
    }
  }
    
   
        System.debug('*****acctIdOpptyListMap ***'+acctIdOpptyListMap);
        System.debug('*********acctIds.size()***'+acctIds.size());
  
        if (acctIds.Size()>0){
        opptyList = [SELECT ID,Amount,AccountId FROM Opportunity WHERE AccountId IN : acctIds];
        System.debug('*****opptyList'+opptyList);
        for(Opportunity oppty : opptyList){
            if(!acctIdOpptyListMap.containsKey(oppty.AccountId)){
                acctIdOpptyListMap.put(oppty.AccountId, new List<Opportunity>());
                System.debug('acctIdOpptyListMap1'+ acctIdOpptyListMap);
            }
            acctIdOpptyListMap.get(oppty.AccountId).add(oppty); 
            System.debug('acctIdOpptyListMap2'+ acctIdOpptyListMap);
        } 
        
        List<Account> acctList = new List<Account>();
        acctList = [SELECT Total_Opportunity_Amount__c FROM Account WHERE Id IN: acctIds];
        System.debug('*******acctList' + acctList);
        if (acctList.size()>0){
        for(Account acct : acctList){
            List<Opportunity> tempOpptyList = new List<Opportunity>();
            tempOpptyList = acctIdOpptyListMap.get(acct.Id);
            System.debug('******** tempOpptyList' +tempOpptyList);
            Double totalOpptyAmount = 0;
            for(Opportunity oppty : tempOpptyList){
                if(oppty.Amount != null){
                    totalOpptyAmount += oppty.Amount;
                    System.debug('********totalOpptyAmount' +totalOpptyAmount);
                }
            }
            acct.Total_Opportunity_Amount__c = totalOpptyAmount;
        }
      }
        if (acctList.size()>0){
        update acctList;
        }
    }

}

I will appreciate any help. Thanks.
Best Answer chosen by Vikas Kumar 135
Khan AnasKhan Anas (Salesforce Developers) 
Hi Vikas,

Greetings to you!

Please try the below code, I have tested in my org and it is working fine. Kindly modify the code as per your requirement.
trigger OppAmountInAcc on Opportunity (after delete,after update,after insert,after undelete) {
    
    set<ID>accIds = new set<ID>();   
    
    if(trigger.isinsert || trigger.isundelete){
        for(Opportunity opp : trigger.new){
            accIds.add(opp.AccountId);
        }
    }
    if(trigger.isdelete){
        for(Opportunity opp : trigger.old){
            accIds.add(opp.AccountId);           
        }        
    }
    
    if(trigger.isupdate){
        for(Opportunity opp:trigger.new){
            accIds.add(opp.AccountId);
            if(trigger.oldmap.get(opp.id).AccountId != opp.AccountId && trigger.oldmap.get(opp.id).AccountId != null ){
                accIds.add(trigger.oldmap.get(opp.id).AccountId);
            }            
        }
    }    
    Map<Id,Double> amtmap = new Map<id,Double>();
    for(AggregateResult ag : [SELECT AccountId ,SUM(Amount) SOA,count(id) cc FROM Opportunity WHERE AccountId IN:accIds GROUP BY AccountId]){
        amtmap.put((ID)ag.get('AccountId'), double.valueof(ag.get('SOA')));
    }
    List<Account>acclist = new List<Account>();
    
    for(Id iid : accIds){
        Account acnt = new Account(Id=iid);
        if(amtmap.containskey(iid)){
            acnt.Total_Opportunity_Amount__c = amtmap.get(iid);
        }else{
            acnt.Total_Opportunity_Amount__c = 0;
        } 
        acclist.add(acnt);       
    }
    
    if(acclist.size()>0){
        UPDATE acclist;
    }
    
}

I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future. It will help to keep this community clean.

Thanks and Regards,
Khan Anas

All Answers

Kamna Jain 8Kamna Jain 8
Hi Vikas,
Thereason you are getting the null pointer is because you are trying to query the opportunity which is already deletd from the system. Instead you can use the trigger.old values only as it has all the fields. I have added the code snippet down, which has few changes:

trigger Opportunity_AIUD on Opportunity (after insert, after update, after delete) {
  if(trigger.isInsert){
      updateAmount(trigger.new);
      system.debug('$$$insert%%%');
  }
  if(trigger.isafter && trigger.isDelete){
      updateAmount(trigger.old);
      system.debug('####delete####');
  }
  
  public void updateAmount(List<Opportunity> opptyList){
      system.debug('$$$$opptyList$$$'+opptyList);
    if(!opptyList.isEmpty()){
        List<Id> acctId = new List<Id>();
        for(Opportunity oppty : opptyList){
            acctId.add(oppty.AccountId);
        }
        system.debug('$$$$acctId$$$'+acctId);
        Map<Id, Account> acctById = new Map<Id, Account>([SELECT Id, Total_Opportunity_Amount__c FROM Account WHERE Id IN: acctId]);
        system.debug('####acctById#####'+acctById);
        for(Opportunity op : opptyList){
            Account acc = acctById.get(op.AccountId);
            system.debug('####acc####'+acc);
            if(trigger.isDelete){
            acc.Total_Opportunity_Amount__c -= op.Amount;
            acctById.put(op.AccountId,acc);
            system.debug('####acctById#####'+acctById);
            }
            else if(trigger.isInsert || trigger.isUpdate){
            acc.Total_Opportunity_Amount__c += op.Amount;
            acctById.put(op.AccountId,acc);
            system.debug('####acctById#####'+acctById);
            }
        }
        update acctById.values();
        system.debug('$$$$final acctById'+ acctById);
    }
    
  }
}

Please see if this helps, or let me know if there is any issue.

Thanks
Kamna 
Vikas Kumar 135Vikas Kumar 135
Hi Kamna,

Thanks for the help. No, the code is not calculating the correct Total_Opportunity_Amount for delete and update event. But this is helpful as I can see that I have to create two methods one for Insert and update and one for delete and then apply the logic.

Regards,
Vikas

 
Khan AnasKhan Anas (Salesforce Developers) 
Hi Vikas,

Greetings to you!

Please try the below code, I have tested in my org and it is working fine. Kindly modify the code as per your requirement.
trigger OppAmountInAcc on Opportunity (after delete,after update,after insert,after undelete) {
    
    set<ID>accIds = new set<ID>();   
    
    if(trigger.isinsert || trigger.isundelete){
        for(Opportunity opp : trigger.new){
            accIds.add(opp.AccountId);
        }
    }
    if(trigger.isdelete){
        for(Opportunity opp : trigger.old){
            accIds.add(opp.AccountId);           
        }        
    }
    
    if(trigger.isupdate){
        for(Opportunity opp:trigger.new){
            accIds.add(opp.AccountId);
            if(trigger.oldmap.get(opp.id).AccountId != opp.AccountId && trigger.oldmap.get(opp.id).AccountId != null ){
                accIds.add(trigger.oldmap.get(opp.id).AccountId);
            }            
        }
    }    
    Map<Id,Double> amtmap = new Map<id,Double>();
    for(AggregateResult ag : [SELECT AccountId ,SUM(Amount) SOA,count(id) cc FROM Opportunity WHERE AccountId IN:accIds GROUP BY AccountId]){
        amtmap.put((ID)ag.get('AccountId'), double.valueof(ag.get('SOA')));
    }
    List<Account>acclist = new List<Account>();
    
    for(Id iid : accIds){
        Account acnt = new Account(Id=iid);
        if(amtmap.containskey(iid)){
            acnt.Total_Opportunity_Amount__c = amtmap.get(iid);
        }else{
            acnt.Total_Opportunity_Amount__c = 0;
        } 
        acclist.add(acnt);       
    }
    
    if(acclist.size()>0){
        UPDATE acclist;
    }
    
}

I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future. It will help to keep this community clean.

Thanks and Regards,
Khan Anas
This was selected as the best answer
Vikas Kumar 135Vikas Kumar 135
Hi Khan Anas,

Thanks a lot for the help. The code is working as expected.

Regards,
Vikas