TransWikia.com

Associating new contacts/cases with an account?

Salesforce Asked by AKor on October 4, 2021

So I’m trying to associate new contacts and cases with an account automatically. I’ve been creating contacts and cases without an account using an automated script. I understand that at this point, I have to use an APEX trigger although the use case is very simple.

I’m very new to APEX triggers, so I didn’t get any further than the logic.

 trigger associateWithAccount on Contact (before insert) {
//get Company__c from Contact
//lookup Accounts by Account Name using Company__c
//get AccountID from the result of that lookup
//insert AccountID from Account into AccountID in Contact
 Map<String, String> extMap = new Map<String, String>();
 Set<String> extIdSet = new Set<String>();
 for(Contact c : Trigger.new){
     extIdSet.add(c.Company__c);
 }
 for(Account a : [select Id, Name from Account where Name IN :extIdSet]){
            extMap.put(a.Id, a.Name);
 }
 for(Contact c : Trigger.new){
     c.Account = extMap.get(c.Id);
 }
}

However, I keep getting the error that I am illegally assigning from String to Account. Any help?

2 Answers

Let's rewrite this with some better variable names while recognizing that Contacts if created from the UI will most likely have their AccountId already populated

trigger associateWithAccount on Contact (before insert) {

 Map<String, Account[]> accountsByCompanyName;  // could be more than one Account w/ same name
 Set<String> searchCompanyNames = new Set<String>();

 // Step 1 - gather search keys
 for(Contact c : Trigger.new){
     if (c.AccountId == null && String.isNotBlank(c.Company__c)) {
        searchCompanyNames.add(c.Company__c);
     }
 }

 // Step 2 - find Accounts by contact.Company__c
 accountsByCompanyName = Util.pivotSObjectsByString(Account.Name,
     [Select Id, Name From Account Where Name IN :searchCompanyNames]);

 // Step 3 - Associate Contact in trigger.new to Account
 for(Contact c : Trigger.new){
    if (c.AccountId != null) {continue;}  // nothing to do 
    Account[] matchingAccounts = accountsByCompanyName.get(c.Company__c);
    if (matchingAccounts.isEmpty()) {continue;} // no match
    if (matchingAccounts.size() > 1) {continue;} // ambiguous - do nothing
    c.AccountId = matchingAccounts[0].Id; // unambiguous match
 }
} 

And handy Util methods (there are other, better flavors of this like SObjectIndex in GitHub)

public static map<String,List<SObject>> pivotSObjectsByString(Schema.SObjectField fldToken, SObject[] sobjList) {
    map<String,List<SObject>>   res = new map<String,List<SObject>> ();
    for (Sobject sobj: sobjList == null ? new list<Sobject>() : sobjlist) {
        String pivotKey = (String) sobj.get(fldToken);
        if (res.containsKey(pivotKey)) {
            res.get(pivotKey).add(sobj);
        }
        else {
            Sobject[] typedSobjs = makeTypedSobjList(sobj); // do this so resulting list.getSobjectType() doesn't return null
            typedSobjs.add(sobj);
            res.put(pivotKey,typedSobjs);
        }
    }
    return res;
}

public static Sobject[] makeTypedSobjList(Sobject sobj) {
    return (Sobject[]) Type.forName('List<'+sobj.getSObjectType()+'>').newInstance();
}

Answered by cropredy on October 4, 2021

Welcome to the wonderful world of Apex! A couple of points:

Typically if we want to fill in data on a record when it's being added into the system, we want to do this in the "Before" stage. Otherwise, we're performing essentially 2 operations for every record, which isn't very safe.

Your overall order of operations is right on the money, though!

Here is a trigger example from stack-exchange that is doing essentially the same thing : How to use External Ids in a Before Insert trigger? . Check out the accepted answer there :-)

Answered by Adam Michael Daw on October 4, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP