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
brozinickrbrozinickr 

Activity Roll Up Field on Account Help

Hello, I'm having some issues with a trigger I wrote to roll up all of the tasks on Account.  It works when I create or update the tasks, but it's failing to work when I delete a task.  It mentions the null object error, which I'm not sure how that makes sense because the task isn't null.  I am pretty sure I was accounting for it, but it keeps on throwing this error:

 

ctivity_Count: execution of AfterDelete caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.Activity_Count: line 9, column 1

 

 

trigger Activity_Count on Task (after insert, after update, after delete, after undelete) 
{
    List<Id> taskIds = new List<Id>();
    List<Id> accIds = new List<Id>();
    Map<Id,Account> accMap = new Map<Id,Account>();
    List<Account> updateList = new List<Account>(); 
    

    for(Task t : Trigger.new)    //line it's failing on
    {
        taskIds.add(t.Id);
        String str = t.whatId;
        if(str.startsWith('001'))     // Task belongs to Account
        {
            accIds.add(t.whatId);
        }
    }
    
    if(accIds.size() > 0)
    {
        for(Account ac : [SELECT Id, Activity_Count__c FROM Account WHERE Id in :accIds])
        {
            accMap.put(ac.Id,ac);
        }

        for(AggregateResult ar : [SELECT Count(Id) c, WhatId w FROM Task WHERE whatId IN :accIds and Subject Like 'Call' and CreatedDate = This_Month GROUP BY WhatId])
        {
            Account acc = new Account();
            
            string str = string.valueOf(ar.get('w'));
            
            acc = accMap.get(str);   // Edited   //
            acc.Activity_Count__c = Integer.valueOf(ar.get('c'));   // Edited
            
            updateList.add(acc);
        }
    }
    
    if(updateList.size() > 0)
    {
        update updateList;
    }
}

 

 

 

 

 

 

 

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
Ritesh AswaneyRitesh Aswaney
Declare an variable with the other stuff you've declared before the for loop(where you've defined your Lists), so that you don't run out of describes. (There is a governor limit around how many describe you can use) Sting accPrefix = Account.sObjectType.getDescribe().getKeyPrefix(); Then where you're comparing reference the variable your declared above If(str!=null && str.startsWith(accPrefix)) //do your stuff Sent from my iPhone

All Answers

Ritesh AswaneyRitesh Aswaney

When the trigger is invoked by a delete event, there is no trigger.new, only a trigger.old is available in context.

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_context_variables.htm

 

 

  for(Task t : (if Trigger.isDelete ? Trigger.old : Trigger.new) )
brozinickrbrozinickr

Thanks Ritesh for your help!  I was able to get it to fire for deletes.  I wrote the test coverage and tried to deploying it, but it was causing trigger exceptions in our org so I had to deploy it.  I'm getting the 'attempt to dereference a null object" error message on line 12 (marked below).  I thought it might have something with the ids being different in the the dev and in production, but the first three digits should be the same for both orgs.

 

trigger Activity_Count on Task (after insert, after update, after delete) 
{
    List<Id> taskIds = new List<Id>();
    List<Id> accIds = new List<Id>();
    Map<Id,Account> accMap = new Map<Id,Account>();
    List<Account> updateList = new List<Account>(); 
    
    for (Task t : Trigger.isDelete ? Trigger.old : Trigger.new)
    {
        taskIds.add(t.Id);
        String str = t.whatId;
        if(str.startsWith('001'))      //line it's failing on
          {
            accIds.add(t.whatId);
          }
    }
    
    if(accIds.size() > 0)
    {
        for(Account ac : [SELECT Id, Activity_Count__c FROM Account WHERE Id in :accIds])
        {
            accMap.put(ac.Id,ac);
        }

        for(AggregateResult ar : [SELECT Count(Id) c, WhatId w FROM Task WHERE whatId IN :accIds and Subject Like 'Call' and CreatedDate = This_Month and IsBigDealRep__c = false GROUP BY WhatId])
        {
            Account acc = new Account();
            
            string str = string.valueOf(ar.get('w'));
            
            acc = accMap.get(str); 
            acc.Activity_Count__c = Integer.valueOf(ar.get('c'));
            
            updateList.add(acc);
        }
    }
    
    if(updateList.size() > 0)
    {
        update updateList;
    
    }
}

 

Ritesh AswaneyRitesh Aswaney

You might want to add a not null check in the event the whatId is null. Accounts will always start with 001 no matter which org. (You may want to use Account.sObjectType.getDescribe().getKeyPrefix() instead of hard-coding 001, if you wanted)


So

 

if(str != null && str.startsWith('001'))    
brozinickrbrozinickr

Thanks Ritesh for your help.  If I wanted to use the Account.sObjectType.getDescribe().getKeyPrefix() method, can I just put that in my if statement?

Ritesh AswaneyRitesh Aswaney
Declare an variable with the other stuff you've declared before the for loop(where you've defined your Lists), so that you don't run out of describes. (There is a governor limit around how many describe you can use) Sting accPrefix = Account.sObjectType.getDescribe().getKeyPrefix(); Then where you're comparing reference the variable your declared above If(str!=null && str.startsWith(accPrefix)) //do your stuff Sent from my iPhone
This was selected as the best answer