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
Preeti ShettyPreeti Shetty 

Update contact field from activity.

I have a field called "Call_Count__c" which is a number field in Contact. I want that when some one logs a call and if the Subject Category is "Call" or "Update" the Call Count field should increase by 1. for eg if value in call count field is 3 it should become 1. Please help me with a trigger for this.
Best Answer chosen by Preeti Shetty
Prosenjit Sarkar 7Prosenjit Sarkar 7
Hi Preeti ,
This is your Trigger,
 
trigger ActivityTrigger on Task (after insert, after update) {
	ActivityTriggerHandler handler = new ActivityTriggerHandler();
    handler.updateCallCount(Trigger.New);
}

and this is your trigger handler,
 
public class ActivityTriggerHandler {
    private final String SUBJECT_CALL = 'Call';
    private final String SUBJECT_UPDATE = 'Update';
    private final String CONTACT_API = 'Contact';
    
    public void updateCallCount(List<Task> taskList) {
        Set<Id> contactIdSet = getContactIds(taskList);
        List<Contact> contactList = [SELECT Call_Count__c FROM Contact WHERE Id IN :contactIdSet];
        updateContacts(contactList);
    }
    
    private Set<Id> getContactIds(List<Task> taskList) {
        Set<Id> contactIdSet = new Set<Id>();
        for(Task t : taskList) {
            if(t.Subject == SUBJECT_CALL | t.Subject == SUBJECT_UPDATE) {
            	Id whoId = t.WhoId;
                if(whoId.getSObjectType().getDescribe().getName() == CONTACT_API)
                    contactIdSet.add(whoId);
            }
        }
        return contactIdSet;
    }
    
    private void updateContacts(List<Contact> contactList) {
        for(Contact con : contactList) {
            if(con.Call_Count__c == NULL || con.Call_Count__c == 0)
                con.Call_Count__c = 1;
            else if(con.Call_Count__c >= 1)
                con.Call_Count__c = con.Call_Count__c + 1;
        }
        update contactList;
    }
}

 

All Answers

NagaNaga (Salesforce Developers) 
Hi Preeti,


You need to write a trigger on Task after update/insert, that loops through trigger.new, checking to make sure that the task has a value for the WhoId and it is a contact. I'm not going to write the whole thing, but this should get you started

trigger UpdateContactOnTaskInsertUpdate on Task (after insert,after update){
List contact_ids = new List(); 
List update_contacts = new List(); 

for(Task t : trigger.new){
//if the whoid is a contact and the status is completed
if(t.WhoId instanceOf Contact && t.Status == 'Completed'){
contact_ids.add(t.WhoId);
}
}

//if the id list is not empty
if(!contact_ids.isEmpty()){
loop through associated contacts with completed tasks 
for(Contact c : [SELECT fields_to_update FROM Contact WHERE ID IN :contact_ids){
//do updates here and add to list for dml
update_contacts.add(c)
}
}

//do dml 
update update_contacts; 
}

That will get you started, but you are going to have to fill in your own logic and I would recommend if you are having trouble getting a trigger like this started, to review the apex developer guides. Next time I won't write that much for you, everybody gets one ;)


Best Regards
Naga Kiran
Beer NutthawanBeer Nutthawan
Hi Preeti

You can try this: 
 
trigger TaskHandlingOnUpdate on Task (after insert)
{
    //Call_Count__c
    MAP<ID,Integer> mapCallCount = new MAP<ID,Integer>();
    for(Task rec: Trigger.new){
        //check if incoming record is for Contact ID
        if(Contact.sObjectType.getDescribe().getKeyPrefix()==String.valueof(rec.whoId).substring(0,3)){
           if(rec.Subject.equalsignorecase('Call') && rec.Status.equalsignorecase('Completed')){
               //Support Bulk inserts
               if(mapCallCount.containskey(rec.WhoId)){
                   Integer intCountCall = mapCallCount.get(rec.WhoId) + 1;
                   mapCallCount.remove(rec.WhoId);
                   mapCallCount.put(rec.WhoId,intCountCall);
               }else{
                   mapCallCount.put(rec.WhoId,1);
               }
            }
        }else{
            //This is a Task created for other objects
        }
    }   
    //Out of for loop
    List<Contact> listOfContacts  = new List<Contact>();
    if(!mapCallCount.isEmpty()){
        //Select existing Call_Count__c from Contact
        for(Contact rec: [select Id, Call_Count__c FROM Contact WHERE ID in:mapCallCount.keyset()]){
            if(mapCallCount.containskey(rec.Id)){ 
                //Temp contact with new Call_Count__c value which calculated by Call_Count__c +
                Decimal delCount= Decimal.valueof(mapCallCount.get(rec.Id));
                if(rec.Call_Count__c!=null){
                    delCount = rec.Call_Count__c + delCount;
                }
                Contact con = new Contact(Id=rec.Id, Call_Count__c=delCount);
                listOfContacts.add(con);
            }
        }
        if(!listOfContacts.isEmpty()){ //Upadte Contact with new Call_Count__c values 
            update listOfContacts;
        }
    }
}

 
Prosenjit Sarkar 7Prosenjit Sarkar 7
Hi Preeti ,
This is your Trigger,
 
trigger ActivityTrigger on Task (after insert, after update) {
	ActivityTriggerHandler handler = new ActivityTriggerHandler();
    handler.updateCallCount(Trigger.New);
}

and this is your trigger handler,
 
public class ActivityTriggerHandler {
    private final String SUBJECT_CALL = 'Call';
    private final String SUBJECT_UPDATE = 'Update';
    private final String CONTACT_API = 'Contact';
    
    public void updateCallCount(List<Task> taskList) {
        Set<Id> contactIdSet = getContactIds(taskList);
        List<Contact> contactList = [SELECT Call_Count__c FROM Contact WHERE Id IN :contactIdSet];
        updateContacts(contactList);
    }
    
    private Set<Id> getContactIds(List<Task> taskList) {
        Set<Id> contactIdSet = new Set<Id>();
        for(Task t : taskList) {
            if(t.Subject == SUBJECT_CALL | t.Subject == SUBJECT_UPDATE) {
            	Id whoId = t.WhoId;
                if(whoId.getSObjectType().getDescribe().getName() == CONTACT_API)
                    contactIdSet.add(whoId);
            }
        }
        return contactIdSet;
    }
    
    private void updateContacts(List<Contact> contactList) {
        for(Contact con : contactList) {
            if(con.Call_Count__c == NULL || con.Call_Count__c == 0)
                con.Call_Count__c = 1;
            else if(con.Call_Count__c >= 1)
                con.Call_Count__c = con.Call_Count__c + 1;
        }
        update contactList;
    }
}

 
This was selected as the best answer
Preeti ShettyPreeti Shetty
Thank you everyone. I have used Prosenjit's trigger. It is working fine. Thanks Beer & Naga for your help.
 
Preeti ShettyPreeti Shetty
Hi All,

Due to some changes in requirement i have updated the above trigger handler given by Prosenjit Sarkar as below
 
public class ActivityTriggerHandler {
    private final String SUB_CATEGORY_CALL = 'Call';
    private final String SUB_CATEGORY_UPDATE = 'Update';
    private final String CONTACT_API = 'Contact';
    
    public void updateCallCount(List<Task> taskList) {
        Set<Id> contactIdSet = getContactIds(taskList);
        List<Contact> contactList = [SELECT Call_Count__c FROM Contact WHERE Id IN :contactIdSet];
        updateContacts(contactList);
    }
    
    private Set<Id> getContactIds(List<Task> taskList) {
        Set<Id> contactIdSet = new Set<Id>();
        for(Task t : taskList) {
            if(t.Sub_Category__c == SUB_CATEGORY_CALL | t.Sub_Category__c == SUB_CATEGORY_UPDATE) {
                Id whoId = t.WhoId;
                if(whoId.getSObjectType().getDescribe().getName() == CONTACT_API)
                    contactIdSet.add(whoId);
            }
        }
        return contactIdSet;
    }
    
    private void updateContacts(List<Contact> contactList) {
        for(Contact con : contactList) {
            if(con.Call_Count__c == NULL || con.Call_Count__c == 0)
                con.Call_Count__c = 1;
            else if(con.Call_Count__c >= 1)
                con.Call_Count__c = con.Call_Count__c + 1;
        }
        update contactList;
    }
}
But while deploying in Production it is giving me the following error -

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, ActivityTrigger: execution of AfterInsert caused by: System.NullPointerException: Attempt to de-reference a null object Class.ActivityTriggerHandler.getContactIds: line 17, column 1 Class.ActivityTriggerHandler.updateCallCount: line 7, column 1 Trigger.ActivityTrigger: line 3, column 1: []
Stack Trace: Class.TestUpdateAccountEngScore.myUnitTest: line 61, column 1

Can you please help me with this.
Prosenjit Sarkar 7Prosenjit Sarkar 7
change the line 17 as 
if(whoId != NULL && whoId.getSObjectType().getDescribe().getName() == CONTACT_API)