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
Daniel GarlickDaniel Garlick 

Apex trigger for cross object field update of unrelated record

I am new to Apex and need help with creating an Apex trigger to update an unrelated record in another object. Our Salesforce instance is being used for both Sales teams tracking in addition to tracking customer's utilization of our services. When a customer signs up for our service, we create an account (with the account type of customer), contact and insert data into several other custom objects. When the account is created, I need to grab the account name (an email address) and then search contacts (other than the one related to the newly created account) and update a checkbox to true 
Any help I can get will be greatly apprecated.

Dan
Best Answer chosen by Daniel Garlick
Neetu_BansalNeetu_Bansal

Hi Daniel,

Try this code, at several points I have specified some comments, where you need to update the exact API name of your fields. Please do that.

trigger AccountTrg on Account( after insert )
{
    List<Contact> contacts = new List<Contact>();
    
    Set<String> accNames = new Set<String>();
    for( Account acc : trigger.new )
    {
        accNames.add( acc.Name );
    }
    
    Map<String, List<Contact>> accToContactMap = new Map<String, List<Contact>>();
    
    for( Contact c : [ Select Id, Name, Email from Contact where Name IN: accNames ]) // Query the checkbox field of Contact
    {
        List<Contact> con;
        if( accToContactMap.containsKey( c.Name ))
        {
            con = accToContactMap.get( c.Name );
        }
        con.add(c);
        accToContactMap.put( c.Name, con );
    }
    
    for( Account acc : trigger.new )
    {
        if( accToContactMap.containsKey( acc.Name ))
        {
            for( Contact c : accToContactMap.get( acc.Name ))
            {
                if( c.AccountId != acc.Id && c.Email == acc.Email ) //Use the account Email field
                {
                    // update the checkbox
                    contacts.add(c);
                }
            }
        }
    }
    
    if( contacts.size() > 0 )
        update contacts;
}

Thanks,
Neetu

All Answers

Neetu_BansalNeetu_Bansal

Hi Daniel,

Try this code, at several points I have specified some comments, where you need to update the exact API name of your fields. Please do that.

trigger AccountTrg on Account( after insert )
{
    List<Contact> contacts = new List<Contact>();
    
    Set<String> accNames = new Set<String>();
    for( Account acc : trigger.new )
    {
        accNames.add( acc.Name );
    }
    
    Map<String, List<Contact>> accToContactMap = new Map<String, List<Contact>>();
    
    for( Contact c : [ Select Id, Name, Email from Contact where Name IN: accNames ]) // Query the checkbox field of Contact
    {
        List<Contact> con;
        if( accToContactMap.containsKey( c.Name ))
        {
            con = accToContactMap.get( c.Name );
        }
        con.add(c);
        accToContactMap.put( c.Name, con );
    }
    
    for( Account acc : trigger.new )
    {
        if( accToContactMap.containsKey( acc.Name ))
        {
            for( Contact c : accToContactMap.get( acc.Name ))
            {
                if( c.AccountId != acc.Id && c.Email == acc.Email ) //Use the account Email field
                {
                    // update the checkbox
                    contacts.add(c);
                }
            }
        }
    }
    
    if( contacts.size() > 0 )
        update contacts;
}

Thanks,
Neetu
This was selected as the best answer
Daniel GarlickDaniel Garlick
Neetu,
      Thanks for your help. This is the final form of what you shared with me, currently awaiting move to production.


trigger AccountTrg on Account( after insert )
{
// Create contact array
    List<Contact> contacts = new List<Contact>();
    Set<String> accNames = new Set<String>();
    for( Account acc : trigger.new )
    {
        accNames.add( acc.Name );
    }
    Map<String, List<Contact>> accToContactMap = new Map<String, List<Contact>>();
    for( Contact c : [ Select Id, Name, Email from Contact where Email IN: accNames ]) // Query the checkbox field of Contact
    {
        List<Contact> con = new List<Contact>();
        if( accToContactMap.containsKey( c.Email ))
            {
                con = accToContactMap.get( c.Email);
            }
        con.add(c);
        accToContactMap.put( c.Email, con );
    }
    for( Account acc : trigger.new )
    {
        if( accToContactMap.containsKey( acc.Name ))
            {
                for( Contact c : accToContactMap.get( acc.Name ))
                    {
                        if(c.Email == acc.Name ) //Use the account Email field
                            {
                                c.Customer_Account_Created__c = true;
                                c.Customer_Account_ID__c = Acc.name;
                                contacts.add(c);
                            }
                    }
            }
    }
    if( contacts.size() > 0 )
    update contacts;
}

As  you can see there was just a few tweeks. For those looking to the unit test code, the following provides 95% coverage.

@isTest
private class accountTriggerUnitTest {
    static testMethod void validateAccountTrigger(){
        Account testAccount=new Account(Name='k+apextest@dufl.com', FirstName__c='kangyi', lastname__c='zhang');
        Contact testContact=new Contact(FirstName='kangyi', LastName='zhang', email='k+apextest@dufl.com');
        insert testContact;
        insert testAccount;
        testContact=[SELECT Id, AccountId FROM Contact WHERE Id=:testContact.Id];
        System.debug('test contact should have a related account with id: '+testContact.AccountId);
        System.assertEquals(true, testContact.Customer_Account_Created__c);
        System.assertEquals(testAccount.Id, testContact.AccountId);
    }
}

 
Daniel GarlickDaniel Garlick
Neetu,
       I am trying to reuse the code you shared with me as a update after trigger. The difference being that I am trying to check the status of an update to a checkbox field on the Account recoard, and then  update the same contact record as in the After insert trigger, but can seem to get it to work. Any chance you could have a quick look to see if something jumps off of the page?

Thanks in advance,

Dan

Here is the code.

trigger AccountTrg2 on Account( after update )
{
// Create contact array
    List<Contact> contacts = new List<Contact>();
    Set<String> accNames = new Set<String>();
    Set<Boolean> accWelcomeKitSent = new Set<Boolean>();
    for( Account acc : trigger.new )
    {
        accNames.add( acc.Name );
        accWelcomeKitSent.add( acc.Welcome_Kit_Sent__c );
    }
    Map<String, List<Contact>> accToContactMap = new Map<String, List<Contact>>();
    for( Contact c : [ Select Id, Name, Email, Welcome_Kit_Sent__c from Contact where Email IN: accNames ]) // Query the checkbox field of Contact
    {
        List<Contact> con = new List<Contact>();
        if( accToContactMap.containsKey( c.Email ))
            {
                con = accToContactMap.get( c.Email);
            }
        con.add(c);
        accToContactMap.put( c.Email, con );
    }
    for( Account acc : trigger.new )
    {
        if( accToContactMap.containsKey( acc.Name ))
            {
                for( Contact c : accToContactMap.get( acc.Name ))
                    {
                        if(c.Email == acc.Name ) //Use the account Email field
                            {
                             if(accWelcomeKitSent.contains(True))
                             {
                              c.Welcome_Kit_Sent__c = True;
                              contacts.add(c);
                              }
                            }
                    }
            }
    }
    if( contacts.size() > 0 )
    update contacts;
Neetu_BansalNeetu_Bansal
Hi Daniel,

Although I didn't understand your requirement, but found some flaws in the trigger. I have updated them, find below the code. In the meantime, can you please explain your requirement. Also, if the above triggers help, please mark it as best answer.

trigger AccountTrg2 on Account( after update )
{
    // Create contact array
    List<Contact> contacts = new List<Contact>();
    
    Set<String> accNames = new Set<String>();
    for( Account acc : trigger.new )
    {
        accNames.add( acc.Name );
    }
    
    Map<String, List<Contact>> accToContactMap = new Map<String, List<Contact>>();
    for( Contact c : [ Select Id, Name, Email, Welcome_Kit_Sent__c, Account.Welcome_Kit_Sent__c from Contact where Email IN: accNames ]) // Query the checkbox field of Contact
    {
        List<Contact> con = new List<Contact>();
        if( accToContactMap.containsKey( c.Email ))
        {
            con = accToContactMap.get( c.Email);
        }
        con.add(c);
        accToContactMap.put( c.Email, con );
    }
    
    for( Account acc : trigger.new )
    {
        if( accToContactMap.containsKey( acc.Name ))
        {
            for( Contact c : accToContactMap.get( acc.Name ))
            {
                if( c.Email == acc.Name && c.Account.Welcome_Kit_Sent__c ) //Use the account Email field
                {
                    c.Welcome_Kit_Sent__c = True;
                    contacts.add(c);
                }
            }
        }
    }
    
    if( contacts.size() > 0 )
        update contacts;


Thanks,
Neetu
Daniel GarlickDaniel Garlick
Neetu, The code below updates c.Welcome_Kit_Sent_c to True anytime that the corresponding Account is updated (it dosen’t matter what field is updated). What I am trying to do is check the Account.Welcome_Kit_Sent_c check box from the acc.name record and then update the one on the Contact record, if the first is set to true. The current check is: if( c.Email == acc.Name && c.Account.Welcome_Kit_Sent__c ). What I think it should be is: if( c.Email == acc.Name && Account.Welcome_Kit_Sent__c == True ). What I am struggling with is getting the detail from the account record Welcome_Kit_Sent__c field. Dan
Neetu_BansalNeetu_Bansal
Hi Daniel,

As per my understanding, you want to update account's contact only if the Welcome kit sent field of account is set to true from false.
Please use below code and let me know if you are still facing any issue.

trigger AccountTrg2 on Account( after update )
{
    // Create contact array
    List<Contact> contacts = new List<Contact>();
    
    Set<String> accNames = new Set<String>();
    for( Account acc : trigger.new )
    {
        accNames.add( acc.Name );
    }
    
    Map<String, List<Contact>> accToContactMap = new Map<String, List<Contact>>();
    for( Contact c : [ Select Id, Name, Email, Welcome_Kit_Sent__c from Contact where Email IN: accNames ]) // Query the checkbox field of Contact
    {
        List<Contact> con = new List<Contact>();
        if( accToContactMap.containsKey( c.Email ))
        {
            con = accToContactMap.get( c.Email);
        }
        con.add(c);
        accToContactMap.put( c.Email, con );
    }
    
    for( Account acc : trigger.new )
    {
        if( !trigger.oldMap.get( acc.Id ).Welcome_Kit_Sent__c
            && acc.Welcome_Kit_Sent__c
            && accToContactMap.containsKey( acc.Name ))
        {
            for( Contact c : accToContactMap.get( acc.Name ))
            {
                if( c.Email == acc.Name ) //Use the account Email field
                {
                    c.Welcome_Kit_Sent__c = true;
                    contacts.add(c);
                }
            }
        }
    }
    
    if( contacts.size() > 0 )
        update contacts;


Thanks,
Neetu
niven sfniven sf
Trigger to update checkbox in contact if contact email and user email are equal
niven sfniven sf
Hi! Send Email Notification to user if email is changed in contact object and also checks if the contact is community user or not
 
niven sfniven sf
Please help me to above requirements