March 21, 2014

Trigger to find total Opportunity amount in Account

Sample Trigger:

trigger Opportunity_AIUD on Opportunity (after insert, after update, after delete) {
    Map<Id, List<Opportunity>> acctIdOpptyListMap = new Map<Id, List<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.isDelete){
        for(Opportunity oppty : trigger.old){
            if(oppty.AccountId != null){
                acctIds.add(oppty.AccountId);
            }
        }    
    }
    if(acctIds.size() > 0){
        opptyList = [SELECT Amount, AccountId FROM Opportunity WHERE AccountId IN : acctIds];
        for(Opportunity oppty : opptyList){
            if(!acctIdOpptyListMap.containsKey(oppty.AccountId)){
                acctIdOpptyListMap.put(oppty.AccountId, new List<Opportunity>());
            }
            acctIdOpptyListMap.get(oppty.AccountId).add(oppty); 
        }   
        List<Account> acctList = new List<Account>();
        acctList = [SELECT Total_Opportunity_Amount__c FROM Account WHERE Id IN: acctIds];
        for(Account acct : acctList){
            List<Opportunity> tempOpptyList = new List<Opportunity>();
            tempOpptyList = acctIdOpptyListMap.get(acct.Id);
            Double totalOpptyAmount = 0;
            for(Opportunity oppty : tempOpptyList){
                if(oppty.Amount != null){
                    totalOpptyAmount += oppty.Amount;
                }
            }
            acct.Total_Opportunity_Amount__c = totalOpptyAmount;
        }
        update acctList;
    }
}

6 comments:

  1. i think this can be done using roll up summary field on account... no need to write trigger for this

    ReplyDelete
    Replies
    1. Yes. But this is for trigger implementation asked in an interview question for my friend.

      Cheers!!!

      Delete
  2. How to do this using Batch Apex. I have tried with same code but result are wrong.

    ReplyDelete
    Replies
    1. You have to fetch Account in start method and Opportunities in execute method. But, it's not a recommended way.

      Delete
  3. Apex trigger Opportunity_AIUD caused an unexpected exception, contact your administrator: Opportunity_AIUD: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 0015g00000R4YrmAAF; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AccountTrigger: execution of BeforeUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 0065g000008xt5HAAQ; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Opportunity_AIUD: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 0015g00000R4YrmAAF; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = 0015g00000R4Yrm) is currently in trigger AccountTrigger, therefore it cannot recursively update itself: [] Trigger.Opportunity_AIUD: line 40, column 1: [] Trigger.AccountTrigger: line 46, column 1: []: Trigger.Opportunity_AIUD: line 40, column 1

    ReplyDelete
    Replies
    1. You are facing recursion error. Check this - https://www.infallibletechie.com/2014/05/maximum-trigger-depth-exceeded.html.

      Delete