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
LoriJLoriJ 

Trigger to update contact address and phone number if account address and phone number change.

Would someone be able to help me write a trigger so that when an account address and phone number change, the address and phone number on all contacts change?  In my perfect world, the phone number would only change on the contact IF before the update they were the same number.  Since I am not a code writer other than when I have to be, I am not sure that is even possible.

 

 

Thanks!

sfdcfoxsfdcfox

It certainly is possible. Here's a rough draft:

 

trigger updateContactsFromAccount on Account (after update) {
  Contact[] updatedContacts = new Contact[0];
  Account[] changedAccounts = new Account[0];
  for(account a:Trigger.new) {
    if(a.phone != trigger.oldmap.get(a.id).phone ||
       a.fax != trigger.oldmap.get(a.id).fax ||
       a.billingstreet != trigger.oldmap.get(a.id).billingstreet || 
       a.billingcity != trigger.oldmap.get(a.id).billingcity ||
       a.billingstate != trigger.oldmap.get(a.id).billingstate || 
       a.billingpostalcode != trigger.oldmap.get(a.id).billingpostalcode ||
       a.billingcountry != trigger.oldmap.get(a.id).billingcountry) {
      changedAccounts.add(a);
    }
  }
  for(Contact c:[select id,accountid,phone,mailingstreet,mailingcity,mailingpostalcode,mailingcountry,mailingstate from contact where accountid in :trigger.new]) {
    account a = trigger.newmap.get(c.accountid);
    boolean updatedrecord = false;
    if(c.phone == trigger.oldmap.get(c.accountid).phone) {
      c.phone = a.phone;
      updatedrecord = true;
    }
    if(c.fax == trigger.oldmap.get(c.accountid).fax) {
      c.fax = a.fax;
      updatedrecord = true;
    }
    if(c.mailingstreet == trigger.oldmap.get(c.accountid).billingstreet) {
      c.mailingstreet = a.billingstreet;
      updatedrecord = true;
    }
    if(c.mailingcity == trigger.oldmap.get(c.accountid).billingcity) {
      c.mailingcity = a.billingcity;
      updatedrecord = true;
    }
    if(c.mailingstate == trigger.oldmap.get(c.accountid).billingstate) {
      c.mailingstate = a.billingstate;
      updatedrecord = true;
    }
    if(c.mailingpostalcode == trigger.oldmap.get(c.accountid).billingpostalcode) {
      c.mailingpostalcode = a.billingpostalcode;
      updatedrecord = true;
    }
    if(c.mailingcountry == trigger.oldmap.get(c.accountid).billingcountry) {
      c.mailingcountry = a.billingcountry;
      updatedrecord = true;
    }
    if(updatedrecord) {
      updatedcontacts.add(c);
    }
  }
  update updatedcontacts;
}

This is a standard "aggregate-query-update" style trigger. First, we gather all accounts that have changed, then we query for all contacts for those accounts and see if they matched the old values, and if so, add them to a list to update, and finally we update the records. Here's a probable test method to go with it.

 

public static testmethod void test() {
  account a = new account(name='test',fax='12345');
  insert a;
  contact[] c = new contact[] {
    new contact(lastname='test',phone='44444',accountid=a.id,mailingstreet='124 main st.',
mailingcity='other',mailingstate='st',mailingpostalcode='54321',mailingcountry='mx'), new contact(lastname='atest',accountid=a.id,fax='12345') }; insert c; a.fax = '23456'; a.mailingstreet = '123 main st.'; a.mailingcity = 'city'; a.mailingstate = 'state'; a.mailingpostalcode = '12345'; a.mailingcountry = 'usa'; a.phone = '23456'; update a; c = [select id,accountid,lastname,phone,fax,mailingstreet,mailingcity,mailingpostalcode,mailingstate,mailingcountry from contact where id in :c order by lastname asc]; system.assertequals(a.fax,c[0].fax); system.assertequals(a.phone,c[0].phone); system.assertequals(a.billingstreet,c[0].mailingstreet); system.assertequals(a.billingcity,c[0].mailingcity); system.assertequals(a.billingstate,c[0].mailingstate); system.assertequals(a.billingpostalcode,c[0].mailingpostalcode); system.assertequals(a.billingcountry,c[0].mailingcountry);
system.assert(c[1].fax != a.fax); // They didn't match before the update.
system.assert(c[1].phone != a.phone);
system.assert(c[1].mailingstreet != a.billingstreet);
system.assert(c[1].mailingcity != a.billingcity);
system.assert(c[1].mailingpostalcode != a.billingpostalcode);
system.assert(c[1].mailingstate != a.billingcountry);
system.assert(c[1].mailingcountry != a.billingcountry);
}

You might want to make it update either the entire address or  not at all instead of field by field, but I thought I'd make it simple to give you an idea that it certainly can be done.

LoriJLoriJ

Sorry for my delay in expressing my appreciation.  Thank you for the help!  This definitely gets me going!

noobfnnoobfn

hi,

I have a similar trigger the only difference is that it triggers before insert and after update, and I'm writting a test and I checked the coverage is 18%, I can't see to cover line 17, line 21, line 25, line 30 to 37, line 45 and line 47.

 

I get an error in my debug log that says :

*******Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, updateContactsOnAddressChange: execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object**********

 

This is my trigger:

trigger updateContactsOnAddressChange on Account (before Insert, after update) {
 2	       
 3	          // I want to find the new address/values on Account by map Id Keys 
 4	           
 5	          Map<Id, Account> acctsWithNewAddresses = new Map<Id, Account>();
 6	       
 7	          // Trigger.new holds my list of the Accounts that will be updated        
 8	          // This loop iterates over the list, and adds any that have new
 9	          // addresses to the acctsWithNewAddresses map. 
 10	           
 11	          for (Integer i = 0; i < Trigger.new.size(); i++) {
 12	              if (   (Trigger.old[i].BillingCity != Trigger.new[i].BillingCity)
 13	                  || (Trigger.old[i].BillingCountry != Trigger.new[i].BillingCountry)
 14	                  || (Trigger.old[i].BillingPostalCode != Trigger.new[i].BillingPostalCode)
 15	                  || (Trigger.old[i].BillingState != Trigger.new[i].BillingState)
 16	                  || (Trigger.old[i].BillingStreet != Trigger.new[i].BillingStreet))  {
 17	                  acctsWithNewAddresses.put(Trigger.old[i].id,Trigger.new[i]);
 18	              }
 19	          }
 20	                           
 21	          List<Contact> contacts = [SELECT id, accountid, MailingCity, MailingCountry, MailingPostalCode,MailingState, MailingStreet
 22	                            FROM Contact
 23	                            WHERE accountId in :acctsWithNewAddresses.keySet()];
 24	              
 25	                      List<Contact> updatedContacts = new List<Contact>();
 26	       System.debug('Kellers ' + contacts);
 27	  
 28	  
 29	          //iterating over each contact in Account
 30	          for (Contact c : contacts) {
 31	              Account parentAccount = acctsWithNewAddresses.get(c.accountId);
 32	              c.MailingStreet = parentAccount.BillingStreet;
 33	              c.MailingCity = parentAccount.BillingCity ;
 34	              c.MailingCountry = parentAccount.BillingCountry ;
 35	              c.MailingPostalCode = parentAccount.BillingPostalCode ;
 36	              c.MailingState = parentAccount.BillingState ;
 37	              c.MailingStreet = parentAccount.BillingStreet ;
 38	      
 39	       
 40	           // Rather than insert the contacts individually, add the         
 41	              // contacts to a list and bulk insert it. This makes the         
 42	              // trigger run faster and allows us to avoid hitting the         
 43	              // governor limit on DML statements 
 44	  
 45	              updatedContacts.add(c);
 46	          }
 47	          update updatedContacts;
 48	      }

 this is my Test: 

@isTest
public class TestUpdateContactsOnAddressChange{
    static testmethod void testAddressChange() {
       //create an account
        Account sAcct = new Account();
       	sAcct.Name = 'Test Account';
          //create account address
        sAcct.BillingStreet = '11 Initial Street'; 
        sAcct.BillingCity = 'Rochester';
        sAcct.BillingPostalCode = '12456';
        sAcct.BillingState = 'NY';
        sAcct.BillingCountry = 'USA';
        Test.startTest();
      	insert sAcct;
       	Test.stopTest();
                
        //create contact for Account "Test Account"
        Contact sContact1 = new Contact();
        	//create contact address
        sContact1.MailingStreet = '1 Initial street';
        sContact1.MailingCity = 'Rochester';
        sContact1.MailingPostalCode = '12456';
        sContact1.MailingState = 'NY';
        sContact1.MailingCountry = 'USA';
       // sContact1.account.id = sAcct.id;
        sAcct.id = sContact1.account.id;
        
        Contact sContact2 = new Contact();
        sContact2.MailingStreet = '2 Initial street';
        sContact2.MailingCity = 'Rochester';
        sContact2.MailingPostalCode = '12456';
        sContact2.MailingState = 'NY';
        sContact2.MailingCountry = 'USA';
        //sContact2.account.id = sAcct.id;
        sAcct.id = sContact2.account.id;
        
        Contact sContact3 = new Contact();
        sContact3.MailingStreet = '3 Initial street';
        sContact3.MailingCity = 'Rochester';
        sContact3.MailingPostalCode = '12456';
        sContact3.MailingState = 'NY';
        sContact3.MailingCountry = 'USA';
        //sContact3.account.id = sAcct.id;
        sAcct.id = sContact3.account.id;
        
        //change address on account
        sAcct.BillingStreet = '11 Updated Street'; 
        sAcct.BillingCity = 'Updated City';
        sAcct.BillingPostalCode = '99999';
        sAcct.BillingState = 'PA';
        sAcct.BillingCountry = 'Mexico';
          
        Test.startTest();
         update sAcct;//this should fire my trigger.
        Test.stopTest();
             
        //check if account updated address match each contact address
       	System.assertEquals(sAcct.BillingStreet, sContact1.mailingstreet); 
        System.assertEquals(sAcct.BillingCity, sContact1.MailingCity); 
        System.assertEquals(sAcct.BillingPostalCode, sContact1.MailingPostalCode); 
        System.assertEquals(sAcct.BillingState, sContact1.MailingState);
        System.assertEquals(sAcct.BillingCountry, sContact1.MailingCountry);
        
        System.assertEquals(sAcct.BillingStreet, sContact2.mailingstreet); 
        System.assertEquals(sAcct.BillingCity, sContact2.MailingCity); 
        System.assertEquals(sAcct.BillingPostalCode, sContact2.MailingPostalCode); 
        System.assertEquals(sAcct.BillingState, sContact2.MailingState);
        System.assertEquals(sAcct.BillingCountry, sContact2.MailingCountry);
        
        System.assertEquals(sAcct.BillingStreet, sContact3.mailingstreet); 
        System.assertEquals(sAcct.BillingCity, sContact3.MailingCity); 
        System.assertEquals(sAcct.BillingPostalCode, sContact3.MailingPostalCode); 
        System.assertEquals(sAcct.BillingState, sContact3.MailingState);
        System.assertEquals(sAcct.BillingCountry, sContact3.MailingCountry);
    }
}

 

Appreciate any help, 

 

  newbee

 

noobfnnoobfn

Thank you. After thinking about this, it made sense to remove "before insert" so I did and it covers my trigger.  

Class slaesforceClass slaesforce
hi noobfn 

   i saw u r works really u r thiniking soo fast and hard work ...
 
Atul Pandey 4Atul Pandey 4
Method:
public static void ChangePhone( List<Account> lstAcc)
    {
        Contact c = new Contact();
        for(Account a : lstAcc)
        {
            c = [Select phone from Contact where AccountId = :a.Id LIMIT 1];
             c.phone = a.Phone;
            update(c);
        }
Trigger:
trigger Trigger_6 on Account (after update ) 
{
    Trigger_Practice_1.ChangePhone(trigger.new);
}
niven sfniven sf
How to write trigger on user object if user email and contact email are same and also user profile is community user.
 
venu Babu 9venu Babu 9
 if Location value is changed then updates related contact location info also with the account location info