+ Start a Discussion
GMASJGMASJ 

How to update account from contacts

Hi, 

  How to update account and parent account when contact is created or updated. 

   Account A  has custom field NSE Count 
   ========
   Contact 1  has custom field  NSE1 which is boolean If NSE1 = true
   Contact 2  has custom field NSE1 which is boolean  if NSE1 = true

   When any contact is updated it should update the Account A NSE Count = 2

   Also if Account A has parent and grand parent it must rollup adding NSE Count 

   Please suggest me the logic how to obtain this in apex. 

Thanks
Sudhir




 
Rahul Singh Rana 9Rahul Singh Rana 9
Hello,

For first part you can write trigger on Contact. I have tried one, let me know if it works for you

trigger UpdateAccountField on Contact (before insert, before Update) {
    HelperClassUpdateAccountField.updateAccountField(trigger.new, trigger.newMap, trigger.oldMap);
}

public class HelperClassUpdateAccountField {
    public static void updateAccountField(List<Contact> conList, Map<ID, Contact> newMap, Map<ID, Contact> OldMap){
        List<Contact> ContactWithFieldChanged = new List<Contact>();
        for(Contact con : conList){
            if(con.NSE1__c != OldMap.get(con.id).NSE1__c){
                ContactWithFieldChanged.add(con);
            }
        }
        if(ContactWithFieldChanged.size() == 0) return;
        List<Account> UpdateContact = new List<Account>();
        for(Contact con : ContactWithFieldChanged){
            if(con.NSE1__c == true){
                con.Account.NSE_Count__c += 1;
            }
            else{
                con.Account.NSE_Count__c -= 1;
            }
            UpdateContact.add(con.Account);
        }
        update UpdateContact;
    }
}

For Second part I think rollup summary should work.

Rahul
 
GMASJGMASJ
Hi Rahul, 

    Thank you very much for your reply. I tried your code there seem to be some issue.  I am getting below error 

Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger ContactTrigger caused an unexpected exception, contact your administrator: ContactTrigger: execution of BeforeUpdate caused by: System.NullPointerException: Attempt to de-reference a null object: ()



In below helper class I just modified the field names to actual fields
public class HelperClassUpdateAccountField {
    public static void updateAccountField(List<Contact> conList, Map<ID, Contact> newMap, Map<ID, Contact> OldMap){
        List<Contact> ContactWithFieldChanged = new List<Contact>();
        for(Contact con : conList){
           // if(con.NSE_1__c != OldMap.get(con.id).NSE_1__c){
                ContactWithFieldChanged.add(con);
          //  }
        }
        if(ContactWithFieldChanged.size() == 0) return;
        List<Account> UpdateContact = new List<Account>();
        for(Contact con : ContactWithFieldChanged){
            if(con.NSE_1__c == true){
                con.Account.NSE_1_Status__c += 1;
            }
            else{
                con.Account.NSE_1_Status__c -= 1;
            }
            UpdateContact.add(con.Account);
        }
        update UpdateContact;
    }
}

Trigger 
 
trigger ContactTrigger on Contact  (before insert, before update){
    HelperClassUpdateAccountField.updateAccountField(trigger.new, trigger.newMap, trigger.oldMap);
}

Please suggest me even the roll up part how to add the logic it will great help from your side. 

Thanks
Sudhir
 








 
GMASJGMASJ
Hi Rahul, 

    I wrote some code which is working need your suggestion on this code for rollup to parent and grand parent

    Below code is working only for one contact it update to parent account 

    If account have two contacts it is not working 
 
    Example. 

    Account A NSE_1_Status__c shold be = 2 
     Contact A  NSE_1__c = true
     Contact B  c.NSE_1__c = true 
ID ContactID = '003W000000mHtAc';
 ID AccountID;
 Contact C = [select id, accountid from contact where id = :ContactID];
 AccountID = C.accountid;
 List<Account> UpdateAccount = new List<Account>();
 List<Contact> ContactWithFieldChanged = new List<Contact>();
 Public static Integer NSEint1 = 0;
 Public static Map<id,integer> NSEmap1 = new Map<id,integer>();
 Public static List<account> NSE1_Update = new List<account>();


 For(account ac : [select name, 
                   (Select id,name,NSE_1__c,NSE_2__c,NSE_3__c,NSE_4__c,NSE_5__c,NSE_7__c,NSE_8__c,
                           NSE_6_FortiMail__c, NSE_6_FortiWeb__c, NSE_6_FortiWireless__c, 
                           NSE_6_FortiAuthenticator__c, NSE_6_FortiADC_D__c, NSE_6_FortiADC_E__c, NSE_6_FortiDDos__c, 
                           NSE_6_FortiSandbox__c,NSE_6_FortiWireless_Controller__c 
                           from contacts)
                   from account where id = :AccountID ] ){
    For(Contact c : ac.contacts ){
       system.debug('Contact Name ' + c.name);  
        if(c.NSE_1__c == true){
          NSEint1 = NSEint1 +1;            
        }                  
    }       
     NSEmap1.put(ac.id,NSEint1);                  
 }    

   if(NSEmap1.size()>0){ 
      For(Id i : NSEmap1.keyset()){        
           Account ains = new Account();
           ains.id = i;
        
           system.debug('Account' + i);       
           system.debug(NSEmap1.get(i));
          
           ains.NSE_1_Status__c = NSEmap1.get(i);
           NSE1_Update.add(ains);                      
            }
        }
             
    if(NSE1_Update.size()>0)           
          
        update NSE1_Update;

Please suggest

Thanks
Sudhir
Rahul Singh Rana 9Rahul Singh Rana 9
Hello, 

Sorry i did not test the code before positing it. I have modified it. Still I have not considered all the scenarios and Bulk test. If you need help with test Class, do let me know. May I also ask what is the business functionality here, May be I will be able to help more.

Also in below code change NSE1 to NSE2.
trigger contactTriggerAcc on Contact (after insert, before update, before delete) {
    if(trigger.isAfter && trigger.isInsert){
        HelpercontactTriggerAcc.insertCollection(trigger.new);
    }
    if(trigger.isBefore && trigger.isUpdate){
        HelpercontactTriggerAcc.updateCollection(trigger.new, trigger.newMap, trigger.oldMap);
    }
    if(trigger.isBefore && trigger.isDelete){
        HelpercontactTriggerAcc.deletehandle(trigger.old);
    }
}
 
public class HelpercontactTriggerAcc {
    public static void insertCollection(List<Contact> conList){
        List<Contact> consWithValue = new List<Contact>();
        for(Contact con : conList){
            if(con.NSE2__c == true){
                consWithValue.add(con);
            }
        }
        updateAccount(consWithValue);
    }
    
    public static void updateCollection(List<Contact> conList, Map<Id, Contact> conMap, Map<Id, Contact> oldMap){
        List<Contact> consWithValueChange = new List<Contact>();
        for(Contact con : conList){
            if(con.NSE2__c != oldMap.get(con.id).NSE2__c){
                consWithValueChange.add(con);
            }
        }
        updateAccount(consWithValueChange);
    }
    
    public static void updateAccount(List<Contact> conList){
       Set<Id> AccountIDs = new Set<Id>();
        for(Contact con : conList){
            AccountIDs.add(con.AccountID);
        }
        Map<Id, Account> accountMap = new Map<Id, Account>([Select NSE_Count__c from Account where Id in :AccountIDs]);
        for(Contact conloop : conList){
            if(conloop.NSE2__c == true){
                if(accountMap.get(conloop.accountID).NSE_Count__c == null) 
                    accountMap.get(conloop.accountID).NSE_Count__c = 0;
                accountMap.get(conloop.accountID).NSE_Count__c += 1;
            }
            else{
                accountMap.get(conloop.accountID).NSE_Count__c -= 1;
            }
        }
        update accountMap.values();
    }
    
    public static void deletehandle(List<Contact> conList){
        Set<Id> AccountIDs = new Set<Id>();
        for(Contact con : conList){
            AccountIDs.add(con.AccountID);
        }
        Map<Id, Account> accountMap = new Map<Id, Account>([Select NSE_Count__c from Account where Id in :AccountIDs]);
        for(Contact conloop : conList){
            if(accountMap.get(conloop.accountID).NSE_Count__c == null) return;
            accountMap.get(conloop.accountID).NSE_Count__c -= 1;
		}
        update accountMap.values();
    }
}



Best Regards,
Rahul Singh Rana
GMASJGMASJ
Hi Rahul,

   You code is working now but it is not rolling up the value to parent and grand parent Please suggest me how to achive this soloution. 

   Also your code is not rolling up the multiple contacts to same account as I gave example 

   Example. 

    Account A NSE_1_Status__c shold be = 2 
     if Contact A  NSE_1__c = true
    if  Contact B  c.NSE_1__c = true 

  Both the contact value should be added to account same logic it should travers to Account A parent and its grand top parent. 
  
   Thank you very much for your help. 

Thanks
Sudhir




 
Rahul Singh Rana 9Rahul Singh Rana 9
Hello,

Parent to Grand Parent functionality I have not included(as I did not understand your requirment), but the code I have checked it before posting. it is rolling up in my Org, my be you have some trigger or functionity that prevents this trigger from adding, thats why I asked the Business Requirement and flow to understand your situation better.

Best Regards,
Rahul Singh Rana
GMASJGMASJ
Hi Rahul, 

    Thank you very much for you reply and help here is the complete requirement please see below image. 

     In Account we have a custom field NSE_1_Status__c (Integer data type)
     In Contact we  have a custom field NSE_1__c ( Boolean data type)

     In salesforce we have account hierarchy that is how below image account are hierarchy displayed. 
     When contact is created or updated and NSE_1__c boolean value is changed it must roolup the count to account and parent accounts 

  User-added image

   Your code is working only thing it is not rolling up Please let me know if your still not clear I can explain 

Thanks
Sudhir

 
Rahul Singh Rana 9Rahul Singh Rana 9
Hello,

You can add 1 function like below to 
 
public static void updateParent(id parentId, String operation){
        for(Account parentAcc : [Select NSE_Count__c, parentId from Account where id = :parentId]){
            //System.debug('++++++++++++++++++++++++' + parentId);
            //System.debug('++++++++++++++++++++++++' + parentAcc);
            if(parentAcc.NSE_Count__c == null) parentAcc.NSE_Count__c = 0;
            if(operation == 'add') parentAcc.NSE_Count__c += 1;
            if(operation == 'sub') parentAcc.NSE_Count__c -= 1;
            update parentAcc;
            if(parentAcc.ParentId == null) break;
            else parentAcc.ParentId = parentId;
        }
    }

and pass values
 
if(accountMap.get(conloop.accountID).Parent  != null){
                    updateParent(accountMap.get(conloop.accountID).Parentid, 'add');
                }

or
 
if(accountMap.get(conloop.accountID).Parent  != null){
                    updateParent(accountMap.get(conloop.accountID).Parentid, 'sub');
                }

But this code will only cover if parent is alreay present. For senario in which parent is created, you may want to write similar trigger on Account Object. Also, I would suggest you to put default value on NSE_Count__c, may be 0, so that it does not run into nullPointerException. 

In contact trigger I also suggest that you add a validate for account or add some funtionality to skip it may be something in trigger that checks it and then only calls the helper class, as the above prevents contact from saving, if no account is present.

You can also consider  process builder for your requirment.  Do you really have to use trigger?

Let me know if you need futher assitance.

Best Regrds,
Rahul
GMASJGMASJ
Hi Rahul, 

    Thanks for your reply I executed you code it is updating only the first parent its not updating the grand parent and top parent. Please see the logic its only till parent 

Thanks
Sudhir
Rahul Singh Rana 9Rahul Singh Rana 9
Yes, that's what I am saying it won't be good idea to write that logic in this but in Account trigger as you won't be able to update Accont that are newly linked. If we inculde that login in contact, then same logic will be repeted twice. 
GMASJGMASJ
Hi Rahul,

    Thanks for your reply Sorru I am bit not clear on the logic can you please give me a complete code with just a logic how your to update parenet hierachy 

Thanks
Sudhir