2

I've created a trigger that once a contact is created, it should be associated to an existing Account - if the domain portion of the email address matches one of the strings in a custom field (field name = Domain) on the account object, that account should be used when the new contact is created. If no match is found, the contact should be assigned to default account.

Trigger:

trigger AssociateContact on Contact (before insert) {
    List<String> contactEmaildomains = new List<String>();
    for(Contact contact:Trigger.new){
        contactEmaildomains.add(contact.Domain__c);
    }

    List<Account> accounts = [
        SELECT 
            Id, Domain__c 
        FROM 
            Account
        WHERE 
            Domain__c IN :contactEmaildomains
    ];

    Map<String, Id> domains = new Map<String, Id>();

    for(Contact record: Trigger.new) {
        domains.put(record.Domain__c, null);
    }

    for(Account record: [SELECT Domain__c FROM Account WHERE Domain__c IN :domains.keySet()]) {
        domains.put(record.Domain__c, record.Id);
    }

    for(Contact record: Trigger.new) {
        if(domains.get(record.Domain__c) != null) {
            record.AccountId = domains.get(record.Domain__c);
        }
        else { record.AccountId = '00158000001xLB0';}   
    }
}

The Domains fields on the Account object can contains more than one string (the domain are separated by a comma).

Can anyone please let me know what should be modified in the trigger above in order to do that? Currently I can put only one domain in this field.

0

This is actually a huge pain to do. You need to use a dynamic query to build multiple LIKE statements to query the related accounts. Then for each Contact you need to loop through all of the related Accounts in order to see which has a matching domain or you can put the domains in a map that directs to each account(this is the route I went). My code is untested so it will likely have some minor errors in it.

//Don't use your hardcoded Id.  Search by something that will work between orgs
Id defaultAccountId = [SELECT FROM Account WHERE Name = 'Unattached'].Id;

String filter = '';

//Use a Set of domains from the Contacts so that we don't have duplicate domains that we are adding to the where clause
Set<String> uniqueDomains = new Set<String>();
List<Contact> domainContacts = new List<Contact>();
//NOTE-try to avoid using the object name as the variable name as well
for (Contact cont: Trigger.new)
{
  if (!String.isBlank(cont.Domain__c))
  {
    uniqueDomains.add(cont.Domain__c);
    domainContacts.add(cont);
  } else
  {
    cont.AccountId = defaultAccountId;
  }
}

for (String domain: uniqueDomains)
{
  filter += ' AND Domain__c LIKE \'%' + domain + '\'%';
}

//Only match for Accounts if a domain is marked
if (!String.isBlank(filter))
{
  filter = filter.substring(4);
  String dynamicQuery = 'SELECT Domain__c FROM Account WHERE ' + filter;

  //NOTE-Assign it to a list here instead of in the loop.  When doing a dynamic query you 
  //don't want it inside the for because it will do a cast each iteration of the loop.
  List<Account> accs = Database.query(dynamicQuery);

  //Build a Map here of domains so that we don't have an n^2 loop going on for each Contact
  Map<String, Id> domainMap = new Map<String, Id>();
  for (Account acc: accs)
  {
    for (String domain: acc.Domain__c.split(';'))
    {
      domainMap.put(domain, acc.Id);
    }
  }

  for (Contact cont: domainContacts)
  {
    //Keep in mind, that this will be case sensitive
    cont.AccountId = domainMap.get(cont.Domain__c);
    if (cont.AccountId == null)
    {
      cont.AccountId = defaultAccountId;
    }
  }
}

One thing to watch, is to see how many unique Contact domains you place here, it can cause the dynamic loop to get too large.

| improve this answer | |
  • thank you for the detailed response. Unfortunately, the code doesn't work I get many errors. I will try to modify it – Lihod Rachmilevitch Jan 5 '16 at 16:03
  • What are your errors? The first query at the start needs modified by you, since I don't know what makes your Account as the default. – dphil Jan 5 '16 at 16:05
  • Error: Compile Error: line breaks not allowed in string literals at line 25 column -1 trigger AssociateContact on Contact (before insert) { //Don't use your hardcoded Id. Search by something that will work between orgs Id defaultAccountId = [SELECT Id FROM Account WHERE Name = 'Unattached']; ...... – Lihod Rachmilevitch Jan 5 '16 at 20:36
  • @LihodRachmilevitch Oops. I forgot to refer to .Id at the end of that query there. Fixed it in my code. – dphil Jan 5 '16 at 20:42
  • Error: Compile Error: line breaks not allowed in string literals at line 26 column -1 ---- { filter += ' AND Domain__c LIKE '%' + domain + '%'; } – Lihod Rachmilevitch Jan 5 '16 at 20:46
0

Because your account has multiple domain name on comma seperate. Then you need to do is

Map<String, Id> domains = new Map<String, Id>();
for(Account record: [SELECT Domain__c FROM Account LIMIT 50000])
   if(record.Domain__c  != null)
       domains.put(string.valueOf(record.Domain__c).tolowercase(), record.Id);

and then for loop on trigger

for(Contact record: Trigger.new) {
    if(record.Domain__c != null)
    {
      for(String str : domains)
      {
        if(str.containsIgnoreCase(String.valueOf(record.Domain__c)))
        {
            record.AccountId = domains.get(str);
            break;
        }
      }
      if(record.AccountId == null)
      {

        //assifn default value but don't use hardcodeed id. use Custom setting to store id. 
      }
    }
}

It will help you. and will handle your case.

| improve this answer | |
  • Thanks for the prompt response! I tried to modify the code but I received many errors. Since it's my first trigger I would appreciate if you could help me and write the full code. Is that possible? – Lihod Rachmilevitch Jan 5 '16 at 13:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.