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
ShimbaShimba 

Retrieving activity records whose RelatedTo is of type Account

I'm trying to get the activity records whose RelatedTo is of type Account in order to update Total_Touches field on Account. Somehow it is not getting the Activity records and I'm not getting any error. Below is my code, Any advice please?


    public static set<Id> filterTaskOrEventRecords(List<sObject> lstActivities,map<Id,sObject> mapOldActivities)
    {
        set<Id> setAccountIds = new set<Id>();

        for(sObject objActivity : lstActivities)  
        {
            Boolean isRelatedToCompany = objActivity.get('AccountId') != null ? (((Id)objActivity.get('AccountId')).getsObjectType() == Account.sObjectType ? true : false) : false;
             
            // Filtering records in insert,update and delete case.
            if((trigger.isInsert) || (trigger.isDelete) || trigger.isUpdate)
            {
                 if(isRelatedToCompany) 
                    setAccountIds.add((Id)objActivity.get('AccountId'));
                
                 if( trigger.isUpdate && ((Id)mapOldActivities.get(objActivity.Id).get('AccountId')).getsObjectType() == Account.sObjectType)    
                     setAccountIds.add((Id)mapOldActivities.get(objActivity.Id).get('AccountId'));
            }
        }
        return setAccountIds;
    }
Jerun JoseJerun Jose
Task and Event object records form activities. Activities are related to other objects using the field WHATID. You will need to inspect the value of WHATID to identify if the related record is an account. Your code is very well written. All you have to do is replace the fieldname of AccountID to WhatID.
public static set<Id> filterTaskOrEventRecords(List<sObject> lstActivities,map<Id,sObject> mapOldActivities){
	set<Id> setAccountIds = new set<Id>();

	for(sObject objActivity : lstActivities){
		Boolean isRelatedToCompany = objActivity.get('WhatID') != null ? (((Id)objActivity.get('WhatID')).getsObjectType() == Account.sObjectType ? true : false) : false;
		 
		// Filtering records in insert,update and delete case.
		if((trigger.isInsert) || (trigger.isDelete) || trigger.isUpdate)
		{
			 if(isRelatedToCompany) 
				setAccountIds.add((Id)objActivity.get('WhatID'));
			
			 if( trigger.isUpdate && ((Id)mapOldActivities.get(objActivity.Id).get('WhatID')).getsObjectType() == Account.sObjectType)    
				 setAccountIds.add((Id)mapOldActivities.get(objActivity.Id).get('WhatID'));
		}
	}
	return setAccountIds;
}

P.S. Please use the code blocks when pasting code. It is easier to read and edit.
ShimbaShimba
Jerun,

Thanks for your reply. I have replacaed the field AccountID to WhatID but when I create a related task to an Account, the task gets created on both Accounts but the Total Activities does not get updated right away on the related Account until I create another then it updates. Any ideas please?
Jerun JoseJerun Jose
Can you post the apex trigger code as well? It'll be good to see the complete code that executes.
ShimbaShimba
Jerun,

Below is my task trigger
 
trigger SL_Task on Task (before insert, before update,after insert,after delete,after update) {
	
	SL_TaskTriggerHandler objHandler = new SL_TaskTriggerHandler();
	
	if(trigger.isBefore && trigger.isInsert)
		objHandler.onBeforeInsert(trigger.New);
	else if(trigger.isBefore && trigger.isUpdate)
		objHandler.onBeforeUpdate(trigger.New,trigger.oldMap);
	else if(trigger.isAfter && trigger.isInsert)	
		objHandler.onAfterInsert(trigger.New);
	else if(trigger.isAfter && trigger.isUpdate)		
		objHandler.onAfterUpdate(trigger.New,trigger.oldMap);
	else if(trigger.isAfter && trigger.isDelete)		
		objHandler.onAfterDelete(trigger.oldMap);	
}


Task trigger handler
 
public with sharing class SL_TaskTriggerHandler 
{
	
    // Method called on before Insert of Task record
	public void onBeforeInsert(List<Task> lstTasks)
	{
		updateCharactersAndWordsField(lstTasks,null);
        updateLastTouchDateAccount(lstTasks);
        stripHTMLFromSubject(lstTasks);
	}
	
	// Method called on before update of Task record
	public void onBeforeUpdate(List<Task> lstTasks,map<Id,Task> mapOldTasks)
	{
		updateCharactersAndWordsField(lstTasks,mapOldTasks);
        updateLastTouchDateAccount(lstTasks);
        stripHTMLFromSubject(lstTasks);
	} 
	
	// Method called on After Insert of Task record
	public void onAfterInsert(List<Task> lstTasks)
	{
		populateTouchInfoOnAccount(lstTasks,null);
        updateLastTouchDateAccount(lstTasks);
	}
	
	// Method called on After update of Task record
	public void onAfterUpdate(List<Task> lstTasks,map<Id,Task> mapOldTasks)
	{
		populateTouchInfoOnAccount(lstTasks,mapOldTasks);
	} 
	
	// Method called on After delete of Task record
	public void onAfterDelete(map<Id,Task> mapOldTasks)
	{
		populateTouchInfoOnAccount(mapOldTasks.values(),null); 
	} 
	
	private void stripHTMLFromSubject(List<Task> records)
	{
		for(Task record : records)
		{
			if(!String.isBlank(record.Description))
			{								
				String description  = record.Description;
				
				if(!String.isBlank(description))
				{					
					if(description.length() > 255)
					{
						description = record.Description.unescapeHtml4().left(record.Description.left(255).lastIndexOf(' '));
					}
					else
					{
						description = record.Description.unescapeHtml4().left(255);
					}	
								
					UUtil.UDebug.printDebug('SL_TaskTriggerHandler.stripHTMLFromSubject - description: ' + description);
					
					record.Subject = description.stripHtmlTags();
					
					UUtil.UDebug.printDebug('SL_TaskTriggerHandler.stripHTMLFromSubject - record.Subject: ' + record.Subject);
				}
			}
		}
	}
	
	// Method to update Total_Touches field on Account based on number of Tasks,Events related to Account
	private void populateTouchInfoOnAccount(List<Task> lstTasks,map<Id,Task> mapOldTasks)
	{
		set<Id> setAcctIdsToUpdate = SL_UtilActivityHandler.filterTaskOrEventRecords(lstTasks,mapOldTasks);

		if(!setAcctIdsToUpdate.isEmpty())
			SL_UtilActivityHandler.updateActivityInfoOnAccount(setAcctIdsToUpdate);
	} 

	private void updateCharactersAndWordsField(List<Task> lstTasks,map<Id,Task> mapOldTasks){
		for(Task e : lstTasks) 
		{
			if(trigger.isInsert || ( trigger.isUpdate && e.Description != mapOldTasks.get(e.Id).Description))
			{
			    if(String.isNotBlank(e.Description)) 
			    {
			      e.NumberOfCharacters__c = e.Description.length();
			      e.NumberOfWords__c = e.Description.split('\\s+').size();
				}
			    else {
			      e.NumberOfCharacters__c = 0;
			      e.NumberOfWords__c = 0;
			    }
			}
		}
	}
	
    public void updateLastTouchDateAccount(List<Task> lstTasks)
    {
        if(lstTasks.size() ==1){
        Map<Id, Account> AccountMap = new Map<ID, Account>();
        
        for(Task t: lstTasks){
            AccountMap.put(t.WhatID,null); //This is an issue with it being null when performing DML below
        }
            
        AccountMap.remove(null);
        
		//The putAll can be removed and the query added to the map constructor in this case
        AccountMap.putAll([SELECT ID, NAME, Date_of_Last_Touch__c from Account where ID in :AccountMap.keySet()]);
        
        Set<Account> recordsToUpdate1 = new Set<Account>();
        
        for(Task t: lstTasks)
        {
            if(!AccountMap.isEmpty())
            {
             	Account accountRecord = AccountMap.get(t.WhatID);	
             	
             	if(accountRecord != null)
             	{
	             	if(accountRecord.Date_Of_Last_Touch__c == null || accountRecord.Date_Of_Last_Touch__c < t.ActivityDate)
	             	{
	                    accountRecord.Date_Of_Last_Touch__c  = t.ActivityDate;
	                    
	                    recordsToUpdate1.add(accountRecord);
	             	}
             	}
            }
        }
        
        try
        { 
        	//update AccountMap.values();
        	List<Account> recordsToUpdate = new List<Account>(recordsToUpdate1);
        	update recordsToUpdate;    
        }
        catch(DmlException e)
        {
        	UUtil.Udebug.printExceptionToDebug(e);
        }    
        }
    }
}

Thanks for your help!
Jerun JoseJerun Jose
Hi Shimba,

Your trigger looks good to me. What I would recommend is to try adding debugg statements to verify if you are getting the expected result. I tried executing a simplified version of the code and it gave me positive results.

The code I used is below. The debug statement output was
12:25:28:279 USER_DEBUG [35]|DEBUG|$$$$$$$$$$$$$$ {00190000006ainBAAQ}
public with sharing class SL_TaskTriggerHandler 
{
	
    // Method called on before Insert of Task record
	public void onBeforeInsert(List<Task> lstTasks)
	{
	}
	
	// Method called on before update of Task record
	public void onBeforeUpdate(List<Task> lstTasks,map<Id,Task> mapOldTasks){
	} 
	
	// Method called on After Insert of Task record
	public void onAfterInsert(List<Task> lstTasks)
	{
		populateTouchInfoOnAccount(lstTasks,null);
	}
	
	// Method called on After update of Task record
	public void onAfterUpdate(List<Task> lstTasks,map<Id,Task> mapOldTasks)
	{
		populateTouchInfoOnAccount(lstTasks,mapOldTasks);
	} 
	
	// Method called on After delete of Task record
	public void onAfterDelete(map<Id,Task> mapOldTasks)
	{
		populateTouchInfoOnAccount(mapOldTasks.values(),null); 
	} 
	
	// Method to update Total_Touches field on Account based on number of Tasks,Events related to Account
	private void populateTouchInfoOnAccount(List<Task> lstTasks,map<Id,Task> mapOldTasks)
	{
		set<Id> setAcctIdsToUpdate = SL_TaskTriggerHandler.filterTaskOrEventRecords(lstTasks,mapOldTasks);
		system.debug('$$$$$$$$$$$$$$ '+setAcctIdsToUpdate);
	} 

	public static set<Id> filterTaskOrEventRecords(List<sObject> lstActivities,map<Id,sObject> mapOldActivities){
		set<Id> setAccountIds = new set<Id>();

		for(sObject objActivity : lstActivities){
			Boolean isRelatedToCompany = objActivity.get('WhatID') != null ? (((Id)objActivity.get('WhatID')).getsObjectType() == Account.sObjectType ? true : false) : false;
			 
			// Filtering records in insert,update and delete case.
			if((trigger.isInsert) || (trigger.isDelete) || trigger.isUpdate)
			{
				 if(isRelatedToCompany) 
					setAccountIds.add((Id)objActivity.get('WhatID'));
				
				 if( trigger.isUpdate && ((Id)mapOldActivities.get(objActivity.Id).get('WhatID')).getsObjectType() == Account.sObjectType)    
					 setAccountIds.add((Id)mapOldActivities.get(objActivity.Id).get('WhatID'));
			}
		}
		return setAccountIds;
	}
}

In the populateTouchInfoOnAccount method debug the value of setAcctIdsToUpdate. If the values are as per your expectation, you will need to debug the update logic in the SL_UtilActivityHandler.updateActivityInfoOnAccount(setAcctIdsToUpdate); method instead.
 
ShimbaShimba
Thanks. Let me check and let you know what happens.