0

enter image description hereI am very new to Apex and trying to write a trigger on Task. I appreciate if you can help..

I have a picklist field on Task(name: Result__c), let's say with values A,B,C. If I choose A or B when I create a new task, I want a custom field (Result Count__c) to be updated on the related contact record.

I think;

| Object : Task | | Operation : Insert | | Event : After |

so we need to create the trigger on Task and it needs to be after the insert.

I wrote this but have no idea what else to do or how to continue.

trigger TaskTrigger on Task (after insert) {
    If (Trigger.isAfter && Trigger.isInsert) {
        for (Task taskRec : Trigger.New) {
            List<Contact> conListToUpdate = [SELECT CountCalls__c FROM Contact WHERE Contact.Name = taskRec.WhoId];
            if (taskRec.Activity_Call_Result__c = 'Not Home' OR taskRec.Activity_Call_Result__c = 'Left Message') {
                conListToUpdate.CountCalls__c = conListToUpdate.CountCalls__c + 1;  
            }
        }
    }
}

I tried to select the contact records where the name of the contact is same in the task we are creating so we'd know which contacts to update but just stuck here.

Thanks in advance.

2 Answers 2

2

welcome to StackExchange. This probably is a task that can also be achieved using Flow or using the Declarative Lookup Rollup Summary tool (DLRS). Did you consider that as well?

If you still want to use apex, here's some first tips:

  1. don't do the matching based on name. The taskRec.WhoId contains the Id of the Contact, so that's a much better matching mechanism (also works if 2 contacts have the same name :-) ).
  2. don't do a SOQL query inside a FOR loop. This is against best practices as it can get you over some governor limits quite easily. Collect Contact Id's in the loop, and do the SOQL query outside of the loop (based on the set of contact id's)
  3. also consider scenarios where a Task gets deleted or the picklist value (or even the Contact lookup) gets updated on a Task. You might need to update your counter as well in those scenarios?
  4. this might lead you to conclude that it's better to query all Tasks under a Contact if any relevant insert/update/delete is done to a Task, and then recalculate the total (instead of working with incremental updates of +1 / -1 to the total)....
4
  • You might also want to add that attempting to update a field on a list (conListToUpdate.CountCalls__c) is not going to work.
    – Moonpie
    Commented Nov 13, 2022 at 22:00
  • Thank you so much for taking the time to answer, Guy! I am working on all those. At the same time I am really trying to understand why, how and which order to do things while writing a class/trigger. Do you have any recommendations for me to study (website/course/youtube channel etc..?) Again, thanks a lot for your help.
    – hkntymz
    Commented Nov 15, 2022 at 21:21
  • Thanks for the comment, Moonpie!
    – hkntymz
    Commented Nov 15, 2022 at 21:22
  • there's a quite extensive example here: iterativelogic.com/… You won't need all of this, but it does contain all code examples you need. Commented Nov 16, 2022 at 13:19
0

Use Declarative Lookup Rollup Summary tool (DLRS) as @guy-clairbois suggested. I was also looking for rollup feature in lookup relationship earlier. Still if you want to use apex then you can use Aggregate Result to get count of task. And use that method on Insert & on change of whoid of task record.(Because if whoid is changed then count need to decreased for old contact & increase in new contact). Below is code you can have work around:

    Trigger Handler::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        public class TaskHandler {
            public static void rollUpTaskOnContact(Set<Id> contactIdsSet){
                if(contactIdsSet != null){
                    List<Contact> contactsToBeUpdateWithTaskCount = new List<Contact>();
                    Map<Id,Integer> contactIdWithNoOfTask = new Map<Id,Integer>();
                    for(AggregateResult arr : [SELECT WhoId, Count(ID)noOfTask FROM Task WHERE WhoId =:contactIdsSet AND 
                                               Activity_Call_Result__c IN ('Not Home','Left Message' ) AND Who.Type = 'Contact' 
                                               GROUP BY WhoId ])
                    {
                        Id contactId = (Id)arr.get('WhoId');
                        Integer taskCount = (Integer)arr.get('noOfTask');
                        contactIdWithNoOfTask.put(contactId,taskCount);
                    }
                    if(!contactIdWithNoOfTask.isEmpty()){
                        for(Id contactId :  contactIdWithNoOfTask.keySet()){
                            Integer noOfTask = contactIdWithNoOfTask.get(contactId);
                            Contact objCon = new Contact(Id = contactId ,CountCalls__c = noOfTask);
                            contactsToBeUpdateWithTaskCount.add(objCon);
                        }
                    }
                    if(contactsToBeUpdateWithTaskCount.size()>0){
                        update contactsToBeUpdateWithTaskCount;
                    }
                }
            }
            
            public static void checkTaskInsertedWithContact(List<Task> newTaskList){
                Set<Id> contactIdsSet = new Set<Id>();
                String contact_prefix = Schema.SObjectType.Contact.getKeyPrefix();
                for(Task objTask : newTaskList ){
                    //check if whoid in not null And contact
                    if(objTask.WhoId != null && ((String)objTask.WhoId).startsWith(contact_prefix)){
                        contactIdsSet.add(objTask.WhoId);
                    }
                }
                if(contactIdsSet.size()>0){
                    //call rollup method
                    rollUpTaskOnContact(contactIdsSet);
                }
            }
            
            public static void checkContactIdIsChangedForTask(List<Task> newTaskList,Map<Id,Task> oldMapForTask){
                Set<Id> contactIdsSet = new Set<Id>();
                String contact_prefix = Schema.SObjectType.Contact.getKeyPrefix();
                for(Task objTask : newTaskList){
                    if(objTask.WhoId != oldMapForTask.get(objTask.Id).WhoId){
                        //update task count in both contact(Old & new)
                        if(objTask.WhoId != null && ((String)objTask.WhoId).startsWith(contact_prefix)){
                            contactIdsSet.add(objTask.WhoId);
                        }
                        if(oldMapForTask.get(objTask.Id).WhoId != null && ((String)oldMapForTask.get(objTask.Id).WhoId).startsWith(contact_prefix)){
                            contactIdsSet.add(oldMapForTask.get(objTask.Id).WhoId);
                        }
                    }
                }
                if(contactIdsSet.size()>0){
                    //call rollup method
                    rollUpTaskOnContact(contactIdsSet);
                }
                
            }
        }

Trigger::::::::::::::::::::::::::::::::::::::::::::::::::
trigger TaskTrigger on Task (after insert,after update) {
    if(trigger.isAfter && trigger.isInsert){
        TaskHandler.checkTaskInsertedWithContact(trigger.new);
    }
    if(trigger.isAfter && trigger.isUpdate){
        TaskHandler.checkContactIdIsChangedForTask(trigger.new, trigger.oldMap);
    }
}
1
  • Thanks @whoisnilu for sharing this. I will go over this line by line and try to understand/internalize.
    – hkntymz
    Commented Nov 15, 2022 at 21:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .