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
Chad MoutesChad Moutes 

Apex Trigger to Populate Date Field

Hello,

I would like to write an Apex Trigger on the Task Object that will populate a date field on the Account Object with the Created Date of the Last Activity With a Status of Completed and a Subject of Completed Call.

Anyone have any ideas on how to approach this.
Best Answer chosen by Chad Moutes
Balaji Chowdary GarapatiBalaji Chowdary Garapati
Then the code should work as you expect. Cheers :). Sorry im in hurry didnt notice the minor typos and mistakes im doing :).

Good day.,

Thanks,
Balaji

All Answers

Balaji Chowdary GarapatiBalaji Chowdary Garapati

Hey Chad,

 It's me again :). Have a question, do you want the max of created date to be on the account or the date of task that is current set to completed? 

Either way it would be trigger on task, where you verify if the completed status task belongs to Account (T.whatId prefix should be 001), and process them based on your answer to my above question.

Thanks,
balaji
Chad MoutesChad Moutes
I want the created date of that Task that is closest to todays date. If that makes sense lol.

And It's nice to see you again lol.
Balaji Chowdary GarapatiBalaji Chowdary Garapati

If you want all the tasks that belongs to children of a particular account to be accounted for, then you might need to use "AccountI" field on the Task and process it accordingly.
 

Chad MoutesChad Moutes
Hmmm I don't even know where to start on this one lol.
Balaji Chowdary GarapatiBalaji Chowdary Garapati
Try this code:
Assuming Recent_Completed_Activity__c is the api name of the date field on account
trigger updateRecentActivityOnAccout on Task(after Update,after Insert){

Set<Id>AccountIdSet=new Set<Id>();
List<Account> accountListToUpdate=new List<Account>();
	for(Task task_Record: trigger.new()){
		if(task_Record.WhatId.statsWith('001') && task_Record.Status=='Completed' && task_Record.Subject ='Completed Call' ){
			AccountIdSet.add(task_Record.WhatId);
		}
	}
	


	for(AggregateResult[] aggregrateResult:[select max(createdDate)MaxCDate,WhatId From Task Where WhatId IN : AccountIdSet and Status='Completed' and Subject='Completed Call']){
			accountListToUpdate.add(new Account(id=aggregrateResult.get('WhatId'),Recent_Completed_Activity__c=aggregrateResult.get('MaxCDate')));
	}
	
	
try{

		if(accountListToUpdate!=Null && accountListToUpdate.size()>0){
			Update accountListToUpdate;
		}
	}Catch(Exception e){
		system.debug('Exception ***'+e.getMessage());
	}
}

Hope it helps,

Thanks,
Balaji
Balaji Chowdary GarapatiBalaji Chowdary Garapati
One small change, change the query in second for loop to.,
select max(createdDate)MaxCDate,WhatId From Task Where WhatId IN : AccountIdSet and Status='Completed' and Subject='Completed Call' Group By WhatId

forgot to include group by clause in the previous post.

Thanks,
balaji
Chad MoutesChad Moutes
Balaji,

Sorry about the late response. I was out of the office. Alright so I tried your code, and I changed task_Record to just T. It makes it alittle easier on myself. But anyways. Heres what i have now:
 
trigger LastCompletedCallDate on Task (after insert, after update, after delete) {

    Set<Id> acc_set = new Set<Id>();
    
    List<Account> acc_list = new List<Account>();
    
    for(Task T: Trigger.new()){
        if(T.WhatId.statsWith('001') && T.Status=='Completed' && T.Subject ='Completed Call' ){
            acc_set.add(T.WhatId);
        }
        
     }
     
     for(AggregateResult[] aggregateResult:[SELECT max(createdDate)MaxCDate,WhatId FROM Task WHERE WhatID IN: acc_set AND Status ='Completed' AND Subject ='Completed Call' Group By WhatId]){
         acc_list.add(new Account(Id=aggregateResult.get('WhatId'),Last_Completed_Call__c=aggregateResult.get('MaxCDate')));
         
     }
     
     try{
     
         if(acc_list !=null && acc_list.size()>0){
             update acc_list;
         }
     
     }Catch(Exception e){
         system.debug('Exception ***'+e.getMessage());
      
      }

}

Im receving the following error: Method does not exist or incorrect signature: [Id].statsWith(String) at line 8 column 12
 
Balaji Chowdary GarapatiBalaji Chowdary Garapati
Its a spell mistake, change that if condition to:
 
if(String.valueof(T.WhatId).startsWith('001') && T.Status=='Completed' && T.Subject ='Completed Call' ){
and coming to the naming I agree that shorter var names looks better, but when debugging in future by any person other than you, if you can leave them a clue what that variable is about, they can close the deal easily than guessing what the variable does :).

Hope it helps.

Thanks,
Balaji
Chad MoutesChad Moutes
Now I'm getting this: AND operator can only be applied to Boolean expressions at line 8 column 83
Balaji Chowdary GarapatiBalaji Chowdary Garapati
if(String.valueof(T.WhatId).startsWith('001') && T.Status=='Completed' && T.Subject =='Completed Call' )

Try this
Chad MoutesChad Moutes
Now I'm getting a new error: Method does not exist or incorrect signature: [List<AggregateResult>].get(String) at line 15 column 38

 
Balaji Chowdary GarapatiBalaji Chowdary Garapati
Sorry too many typos.,

Try this version:
 
trigger LastCompletedCallDate on Task (after insert, after update, after delete) {

    Set<Id> acc_set = new Set<Id>();
    
    List<Account> acc_list = new List<Account>();
    
    for(Task T: Trigger.new()){
        if(String.valueof(T.WhatId).statsWith('001') && T.Status=='Completed' && T.Subject=='Completed Call' ){
            acc_set.add(T.WhatId);
        }
        
     }
     
     for(AggregateResult aggregateResult:[SELECT max(createdDate)MaxCDate,WhatId FROM Task WHERE WhatID IN: acc_set AND Status ='Completed' AND Subject ='Completed Call' Group By WhatId]){
         acc_list.add(new Account(Id=aggregateResult.get('WhatId'),Last_Completed_Call__c=aggregateResult.get('MaxCDate')));
         
     }
     
     try{
     
         if(acc_list !=null && acc_list.size()>0){
             update acc_list;
         }
     
     }Catch(Exception e){
         system.debug('Exception ***'+e.getMessage());
      
      }

}

Try this and let me know if you see any more errors
Chad MoutesChad Moutes
Now im getting this error again lol :AND operator can only be applied to Boolean expressions at line 8 column 83
Chad MoutesChad Moutes
I fixed that one, heres the new one: Invalid initial expression type for field Account.Id, expecting: Id at line 15 column 38
Balaji Chowdary GarapatiBalaji Chowdary Garapati
Oops., 
trigger LastCompletedCallDate on Task (after insert, after update, after delete) {

    Set<Id> acc_set = new Set<Id>();
    
    List<Account> acc_list = new List<Account>();
    
    for(Task T: Trigger.new()){
        if(String.valueof(T.WhatId).startsWith('001') && T.Status=='Completed' && T.Subject=='Completed Call' ){
            acc_set.add(T.WhatId);
        }
        
     }
     
     for(AggregateResult aggregateResult:[SELECT max(createdDate)MaxCDate,WhatId FROM Task WHERE WhatID IN: acc_set AND Status ='Completed' AND Subject ='Completed Call' Group By WhatId]){
         acc_list.add(new Account(Id=aggregateResult.get('WhatId'),Last_Completed_Call__c=aggregateResult.get('MaxCDate')));
         
     }
     
     try{
     
         if(acc_list !=null && acc_list.size()>0){
             update acc_list;
         }
     
     }Catch(Exception e){
         system.debug('Exception ***'+e.getMessage());
      
      }

}
Chad MoutesChad Moutes
Still getting this: 
Invalid initial expression type for field Account.Id, expecting: Id at line 15 column 38
Balaji Chowdary GarapatiBalaji Chowdary Garapati
I just saw your latest comment:

Forgot to type cast the id and date values, you can try this final version :)
trigger LastCompletedCallDate on Task (after insert, after update, after delete) {

    Set<Id> acc_set = new Set<Id>();
    
    List<Account> acc_list = new List<Account>();
    
    for(Task T: Trigger.new()){
        if(String.valueof(T.WhatId).startsWith('001') && T.Status=='Completed' && T.Subject=='Completed Call' ){
            acc_set.add(T.WhatId);
        }
        
     }
     
     for(AggregateResult aggregateResult:[SELECT max(createdDate)MaxCDate,WhatId FROM Task WHERE WhatID IN: acc_set AND Status ='Completed' AND Subject ='Completed Call' Group By WhatId]){
         acc_list.add(new Account(Id=(id)aggregateResult.get('WhatId'),Last_Completed_Call__c=(date)aggregateResult.get('MaxCDate')));
         
     }
     
     try{
     
         if(acc_list !=null && acc_list.size()>0){
             update acc_list;
         }
     
     }Catch(Exception e){
         system.debug('Exception ***'+e.getMessage());
      
      }

}

 
Balaji Chowdary GarapatiBalaji Chowdary Garapati
One sec., minor change.,
 
trigger LastCompletedCallDate on Task (after insert, after update, after delete) {

    Set<Id> acc_set = new Set<Id>();
    
    List<Account> acc_list = new List<Account>();
    
    for(Task T: Trigger.new()){
        if(String.valueof(T.WhatId).startsWith('001') && T.Status=='Completed' && T.Subject=='Completed Call' ){
            acc_set.add(T.WhatId);
        }
        
     }
     
     for(AggregateResult aggregateResult:[SELECT max(createdDate)MaxCDate,WhatId FROM Task WHERE WhatID IN: acc_set AND Status ='Completed' AND Subject ='Completed Call' Group By WhatId]){
         acc_list.add(new Account(Id=(id)aggregateResult.get('WhatId'),Last_Completed_Call__c=date.valueof(aggregateResult.get('MaxCDate'))));
         
     }
     
     try{
     
         if(acc_list !=null && acc_list.size()>0){
             update acc_list;
         }
     
     }Catch(Exception e){
         system.debug('Exception ***'+e.getMessage());
      
      }

}

 
Balaji Chowdary GarapatiBalaji Chowdary Garapati
Are you looking for date time or date field on account? 
Chad MoutesChad Moutes
Just Date field is fine
Balaji Chowdary GarapatiBalaji Chowdary Garapati
Then the code should work as you expect. Cheers :). Sorry im in hurry didnt notice the minor typos and mistakes im doing :).

Good day.,

Thanks,
Balaji
This was selected as the best answer
Chad MoutesChad Moutes
Balaji, You always come through in the clutch!

I greatly appreciate all the help!
Chad MoutesChad Moutes
Okay so it works, i created a Activity with a Status of Completed, and a subject of Completed call. And the due date populated into that field. But when i went to go delete it, it gave me this error: There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger LastCompletedCallDate caused an unexpected exception, contact your administrator: LastCompletedCallDate: execution of AfterDelete caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.LastCompletedCallDate: line 7, column 1". 

I even added another completed call and then tried to delete it thinking maybe it wouldn't delete only because there wasnt another record to populate the field but it still gave me the error. Any thoughts?
Balaji Chowdary GarapatiBalaji Chowdary Garapati
I didnt observe that you added delete event :) which doesnt have any trigger.new() as it will not exist., so the code should be ready to handle  this:
 
trigger LastCompletedCallDate on Task (after insert, after update, before delete) {


	
    Set<Id> acc_set = new Set<Id>();
    
    List<Account> acc_list = new List<Account>();
    
	if(trigger.isInsert || trigger.isUpdate){
    for(Task T: Trigger.new()){
        if(String.valueof(T.WhatId).startsWith('001') && T.Status=='Completed' && T.Subject=='Completed Call' ){
            acc_set.add(T.WhatId);
        }
        
     }
	 }
	 if(trigger.isDelete){
		for(Task T: Trigger.old()){
        if(String.valueof(T.WhatId).startsWith('001') && T.Status=='Completed' && T.Subject=='Completed Call' ){
            acc_set.add(T.WhatId);
        }
        
     }
	 }
     
     for(AggregateResult aggregateResult:[SELECT max(createdDate)MaxCDate,WhatId FROM Task WHERE WhatID IN: acc_set AND Status ='Completed' AND Subject ='Completed Call' Group By WhatId]){
         acc_list.add(new Account(Id=aggregateResult.get('WhatId'),Last_Completed_Call__c=aggregateResult.get('MaxCDate')));
         
     }
     
     try{
     
         if(acc_list !=null && acc_list.size()>0){
             update acc_list;
         }
     
     }Catch(Exception e){
         system.debug('Exception ***'+e.getMessage());
      
      }

}

 
Chad MoutesChad Moutes
Alright, well that worked. No more error and the record was deleted. But the field is still populated. Is it possible to make it so the field returns to blank?
Chad MoutesChad Moutes
Also, I wanted to change from Created Date to Activity Date, and I'm now receving this error: field ActivityDate does not support aggregate operator MAX at line 26 column 42

I know I'm so needy sometimes lol.