6

I'm trying to create a trigger on Contacts that automatically creates and associates an Account if one has not been previously created. This was functionality that we had in a managed package that we had to uninstall. My initial effort was as follows.

trigger CreateHouseholdAccount on Contact (before insert) {

RecordType arec = SELECT ID FROM RecordType WHERE SobjectType = 'Account' AND Name = 'Household';
for (Contact c : trigger.new){
    Account acc = new Account();
    if(c.AccountID == null){
        string cName = (c.FirstName + ' ' + c.LastName + ' ' + 'Household');
        acc.name = cName;
        acc.RecordType.id = arec.Id;
        //fill in more account info based on contact         
    insert acc;
    c.AccountID = acc.Id;
    }
  }
}

This code worked just fine but wasn't bulkified properly. A large upload of contacts would break the 50 DML action limit. This is where I'm having trouble. The following code is what I've come up with. It doesn't error out but also leaves the account field blank on the contact.

trigger Contact on Contact (before insert, before update) {

  RecordType arec = [SELECT ID FROM RecordType WHERE SobjectType = 'Account' AND Name = 'Household'];
  Map<Contact, Account> con_acc_map = new Map<Contact, Account>();
  List<Account> list_acc = new List<Account>();

  for (Contact c : trigger.new){
    Account acc = new Account();
    if(c.AccountID == null && c.LastModifiedById != '005G0000001cbVV' ){
        string cName = (c.FirstName + ' ' + c.LastName + ' ' + 'Household');
        acc.name = cName;
        acc.BillingStreet = c.MailingStreet;
        acc.RecordType.id = arec.Id;
        con_acc_map.put(c, acc);

    }
  }

  insert list_acc;

  //update the contacts' account field
  for (Contact c : trigger.new){
    Account a = con_acc_map.get(c); 
    c.AccountId = a.id;
  }

}

From what I can gather, con_acc_map map is not updating the Account objects with their ids from the insert operation. Is there anyway to do that or any alternative you can come up with? Thanks!

10

First off, you need to do this after insert since you need a contact Id to reference. Second, you should use DeveloperName not Name. Third, don't reference RecordType.Id in the creation, instead use RecordTypeId:

trigger CreateHouseholdAccount on Contact (after insert) {

    RecordType arec = [SELECT ID FROM RecordType WHERE sObjectType = 'Account' AND DeveloperName = 'Household'];

    Map<Id, Account> aMap = new Map<Id, Account>();

    for (Contact con : trigger.new){
        if(con.AccountID == null){
            Account acc = new Account();
                acc.name = con.FirstName + ' ' + con.LastName + ' ' + 'Household';
                acc.RecordTypeId = arec.Id;
            aMap.put(con.Id, acc);
        }
    }

    if (!aMap.isEmpty()) {
        insert aMap.values();

        List<Contact> cList = new List<Contact>();

        for (Id cId : aMap.keySet()) {
            Contact con = new Contact();
                con.Id = cId;
                con.AccountId = aMap.get(cId).Id;
            cList.add(con);
        }

        update cList;

    }

}
  • 1
    Great suggestions! Using an after insert and updating the contacts is the piece my brain wasn't able to come up with. Thanks for your help! – dannymorty Oct 16 '13 at 21:04
2

Also we can use

List<RecordType> arecList = [SELECT ID FROM RecordType WHERE sObjectType = 'Account' AND DeveloperName = 'Household'];

and use arecList.get(0) in places of arec;

or use Try Catch method to execute SOQL.

We may never know when SOQL would fail.

  • 2
    Yessir, this is great to add as best practices. You should always run SELECT statements into Lists and try/catch. I was trying to get him to a point where the code worked. @dannymorty you should check this out for better coding practices! – Nathan Williams Oct 16 '13 at 21:27
1

Sounds like you are trying to replicate what the SF Foundation's Non Profit Starter Pack code does. Either way, I would take a look at their source code and use that as a starting point

0

You Can Also use the before insert context of the Trigger that will save the update statement in the end thus reducing a dml count.

Sharing the below code:

Map<Contact,Account> conMap=new Map<Contact,Account>();
for(Contact con:trigger.new){
    if(con.AccountId == null){
        conMap.put(con,new Account(name='Test'+con.lastname));
    }
}
insert conMap.values();
for(Contact con:trigger.new){
    if(con.AccountId == null){
        con.AccountId=conMap.get(con).Id;
    }
}

You can modify as required.

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.