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
AviKesariAviKesari 

Illegal assignment from List to ID - to get whatID

Hi All,

I have trigger on after insert and after update, below is my handler class.

If i create a task from contact(is a required field on page layout) it fails because whatID is null. So I'm trying to query to get the whatID based on whoID.

If i create a task from account, works fine because whoid and whatid are not null.

public with sharing class TaskTriggerHandler {
    
    private boolean trigger_isExecuting = false;
    
    public TaskTriggerHandler(){
        
    }
    
    public void OnAfterInsert(Task[] newObjects){
        // EXECUTE AFTER INSERT LOGIC       updateAccountActivityFields(newObjects);
    }
    
    public void OnAfterUpdate(Task[] oldObjects, Task[] updatedObjects, Map<ID, Task> ObjectMap){
        //EXECUTE AFTER UPDATE LOGIC
        updateAccountActivityFields(updatedObjects);
    }
    

     public void updateAccountActivityFields(Task[] taskRecords){
      
        // find task record type 
        RecordType taskRec = [SELECT Id FROM RecordType WHERE SobjectType ='Task' AND DeveloperName ='Task_Record_Type'];
        
        List<Account> accountsToUpdate = new List<Account>();
        Account a;
       
        //Get all the contactIds and accountIds of the task being inserted/updated
        for(Task tk : [SELECT Id, LastModifiedBy.name, type, LastModifiedDate, CreatedDate, RecordTypeId, whoid, whatid FROM task WHERE id in :taskRecords]){
            if(tk.RecordTypeId == taskRec.Id  && tk.Whoid!=null){
                
                // query to get account ID from contact:whoID 
                a = new Account(Id = [SELECT AccountId FROM Contact WHERE Id =: tk.WhoId]);
                              
                //convert task's CreatedDate, datetime to date
                Date createdDateJustDate = date.newinstance(tk.CreatedDate.year(), tk.CreatedDate.month(), tk.CreatedDate.day());
        
                //update the activity fields on account with Task's lastModifiedDate and LastModifiedBy based on Task Type
                if(tk.type=='Face 2 Face Meeting' || tk.type=='Lunch'){
                    a.Last_Face_to_Face_Activity__c = createdDateJustDate;
                    a.Last_Visited_By__c = tk.LastModifiedBy.name;
      
                }
                else{
                    a.Last_Call_Activity__c =  createdDateJustDate;
                    
                }
                
                accountsToUpdate.add(a);
               
            }
        }
        
       if(!accountsToUpdate.isEmpty())
            Update accountsToUpdate;

Please help!!

JayantJayant
Change this - 
 a = new Account(Id = [SELECT AccountId FROM Contact WHERE Id =: tk.WhoId]);
to -
List<Contact> c =  [SELECT AccountId FROM Contact WHERE Id =: tk.WhoId];
a = new Account(Id = c[0].AccountId);


Also, at any point only one of WhoId or WhatId would be populated, if parent is Lead or Contact - WhoId would be populated and if parent is any other object - WhatId would be populated. User can't have activities as a child.
Raj VakatiRaj Vakati
try this'
public with sharing class TaskTriggerHandler {
    
    private boolean trigger_isExecuting = false;
    
    public TaskTriggerHandler(){
        
    }
    
    public void OnAfterInsert(Task[] newObjects){
        // EXECUTE AFTER INSERT LOGIC       updateAccountActivityFields(newObjects);
    }
    
    public void OnAfterUpdate(Task[] oldObjects, Task[] updatedObjects, Map<ID, Task> ObjectMap){
        //EXECUTE AFTER UPDATE LOGIC
        updateAccountActivityFields(updatedObjects);
    }
    

     public void updateAccountActivityFields(Task[] taskRecords){
      
        // find task record type 
        RecordType taskRec = [SELECT Id FROM RecordType WHERE SobjectType ='Task' AND DeveloperName ='Task_Record_Type'];
        
        List<Account> accountsToUpdate = new List<Account>();
        Account a;
       
        //Get all the contactIds and accountIds of the task being inserted/updated
        for(Task tk : [SELECT Id, LastModifiedBy.name, type, LastModifiedDate, CreatedDate, RecordTypeId, whoid, whatid FROM task WHERE id in :taskRecords]){
            if(tk.RecordTypeId == taskRec.Id  && tk.Whoid!=null){
                
                // query to get account ID from contact:whoID 
                a = new Account(Id = [SELECT AccountId FROM Contact  WHERE Id =: tk.WhoId Limit 1].AccountId);
                              
                //convert task's CreatedDate, datetime to date
                Date createdDateJustDate = date.newinstance(tk.CreatedDate.year(), tk.CreatedDate.month(), tk.CreatedDate.day());
        
                //update the activity fields on account with Task's lastModifiedDate and LastModifiedBy based on Task Type
                if(tk.type=='Face 2 Face Meeting' || tk.type=='Lunch'){
                    a.Last_Face_to_Face_Activity__c = createdDateJustDate;
                    a.Last_Visited_By__c = tk.LastModifiedBy.name;
      
                }
                else{
                    a.Last_Call_Activity__c =  createdDateJustDate;
                    
                }
                
                accountsToUpdate.add(a);
               
            }
        }
        
       if(!accountsToUpdate.isEmpty())
            Update accountsToUpdate;

 
AviKesariAviKesari
Thanks Jayant but does it fail during mass insert/update of task? because we are doing con[0] ? Please can you explain?
JayantJayant
If what you already have does not fail, then using con[0] won't fail either. Since you are giving only 1 Id in filter, only 1 record would be returned.

By the way, your code will fail when the task is on Lead instead of Contact.
JayantJayant
Also, it may fail with Too Many SOQLs since the max SOQLs allowed are 100 and you are performing the query on Contact inside a for loop on tasks.
AviKesariAviKesari
Thanks for the reply Jayant and Raj.

My test class is failing if i use the code by Raj also.

here is the test class:

 static testMethod void testAdminUserwithTask() {
        
        // Next make sure that a System Admin *can* delete an attachment
        Profile adminProf = [select id from profile where name='System Administrator']; 
        User au = new User(alias = 'Admint', email='AdminUser@asdahsdjkhkjashdjasd.com',emailencodingkey='UTF-8',FirstName='Admin',
                           lastname='task',languagelocalekey='en_US',localesidkey='en_US',profileid = adminProf.Id,
                           timezonesidkey='America/Los_Angeles',username='AdminUser@asdahsdjkhkjashdjasd.com');
        // Switch current user to System Admin user
        System.runAs(au) {
            // Create test data (a new Account with an Attachment)
            Account a = new Account(Name='Testtasking');
            insert a;
            Contact con = new Contact(LastName='Test',FirstName='asdasd',Email='asdasd@adsasd.com') ;
            insert con ; 
            List<Task> tasks = new List<Task>{};
                for(Integer i = 0; i < 200; i++) 
            {
                Task t = new Task(Subject='Donni'+i,Status='New',Priority='Normal',Type='Phone Call', whoId =con.Id, whatId = a.Id );
                tasks.add(t);
            }
            test.startTest();
            insert tasks;
            test.stopTest();
            
            try {
                delete tasks;
            } catch (Exception e) {
                
            }
            
        }
    }