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
jjnhjjnh 

updating account fields based on contact fields?

I am having trouble creating a solution for this request.

 

I am looking to update specific account fields (text, picklist, url fields) based on the originating fields inside the contact. In this many-to-one situation, I need to pull the most recently updated field out of the contacts group and the oldest field out of the same group and bring it into the account. 

 

ex. 

Account and Contact Field: Most_recent_visit__c

Contact 1 = Most recent visit = 11/11/09 so the account would need to be updated to that. 

 

Contact 2 comes in and his most recent visit was 11/15/09, now I would need the Account field to be updated to 11/15/09.

 

All help is appreciated. 

jjnhjjnh
This also would need to apply to fields like a text field or a picklist
IanRIanR

Hi,

 

You need a subquery to get Contact details for your Account, then you need to order and limit the subquery to return the one you want.

 

Then you can use the Account.Contacts relationship to set your Account-level data,

 

something like:

 

Account acc = [SELECT a.Name, (SELECT c.Name, c.Most_recent_visit__c FROM a.Contacts c order by Most_recent_visit__c desc) FROM Account a WHERE a.Id =: accountId]; // I am assuming you will know this

if (acc.Contacts.size() > 0)

acc.Most_recent_visit__c = acc.Contacts[0].Most_recent_visit__c;

 

 

 

HTH, Ian

 

:)

 

jjnhjjnh
thank you for the help, i have one more piece to add on. how can i accomplish this as a batch process? there are quite a few fields I have to update and is there a way to update based on field history?
IanRIanR

Couple of questions:

 

1 - by 'batch' do you mean a) Updating many Accounts at once, b) Updating many Contacts at once, or c) Something else?

 

2 - I'm not sure I understand your requirement to update based on field history, could you please elaborate?

 

 

Let me know, and I'll try to help if I can :)

 

 

Cheers, Ian

jjnhjjnh

1. by batch i mean updating many accounts at once from the contact fields, also there will be 9 or 10 fields that will need to be updated in the account

 

2. using field history timestamp i think i could use that to decide if the picklist in contact1 is more recent than the picklist in contact2 and then update the picklist at the account level

 

Thank you for the help :)

IanRIanR

OK - so try creating a trigger on the Account object. Triggers will naturally handle batch inserts and updates and expose a handy property 'New' which is a collection of SObjects being changed...

 

the trigger will look something like:

 

trigger UpdateAccountFromContacts on Account(before insert, before update) {

 

Set<Id> accountIds = new Set<Id>();

for (Account a : Trigger.new)

accountIds.add(a.Id);

 

// Paste your select statement in here.

// Remember to add each required Contact field to the sub-query

// Change your Account 'where' query to get all the accounts in the trigger.

Map<Id, Account> accounts = new Map<Id, Account>( [ SELECT {blah} FROM Account WHERE Id in: accountIds ] );

 

for (Account a : Trigger.new) {

Account accFromMap = accounts.get(a.Id);

if (accFromMap.Contacts.size() > 0) {

a.field1 = accFromMap.Contacts[0].field1;

a.field2 = accFromMap.Contacts[0].field2;

a.field3 = accFromMap.Contacts[0].field3;

etc...

}

} }

 

 

This is untested - so have a play and see if you can get it to work ;)

 

 

If you want to be tricky with which Contact's field to write to the Account on a case-by-case basis (e.g. the 'Last Visited' date from Contact1, but the 'Favourite Sports Team' from Contact 2, you can remove the LIMIT 1 restriction on the subquery, then your account's 'Contacts' object will contain every contact for that account... you can loop through and pick and choose as you please...

 

 

HTH, Ian

jjnhjjnh
Awesome! I got it working. Now the next part is, when a contact is updated with this info how do I get it to update the account?
jjnhjjnh

***edit*** i got it working on the simple path, not the tricky part yet

 

 

 

trigger UpdateAccountFromContacts on Account(before insert, before update) { Set<Id> accountIds = new Set<Id>(); for (Account a : Trigger.new) accountIds.add(a.Id); Map<Id, Account> accounts = new Map<Id, Account>( [ Select a.Id, (Select Most_Recent_Conversion__c, Most_Recent_Inbound_Marketing_Code__c, Most_Recent_Lead_Source__c, Most_Recent_Referring_URL__c, Most_Recent_Visit__c, Original_Inbound_Marketing_Code__c, Original_Lead_Source__c, Original_Referring_URL__c, Original_Visit__c From Contacts) from Account a ] ); for (Account a : Trigger.new) { Account accFromMap = accounts.get(a.Id); if (accFromMap.Contacts.size() > 0) { a.Most_Recent_Conversion__c = accFromMap.Contacts[0].Most_Recent_Conversion__c; a.Most_Recent_Inbound_Marketing_Code__c = accFromMap.Contacts[0].Most_Recent_Inbound_Marketing_Code__c; a.Most_Recent_Lead_Source__c = accFromMap.Contacts[0].Most_Recent_Lead_Source__c; a.Most_Recent_Referring_URL__c = accFromMap.Contacts[0].Most_Recent_Referring_URL__c; a.Most_Recent_Visit__c = accFromMap.Contacts[0].Most_Recent_Visit__c; a.Original_Inbound_Marketing_Code__c = accFromMap.Contacts[0].Original_Inbound_Marketing_Code__c; a.Original_Lead_Source__c = accFromMap.Contacts[0].Original_Lead_Source__c; a.Original_Referring_URL__c = accFromMap.Contacts[0].Original_Referring_URL__c; a.Original_Visit__c = accFromMap.Contacts[0].Original_Visit__c; } } }

 

next is to have this update the account when the contact is updated and to have the contact1 vs contact2 situation come into play


 

Message Edited by jjnh on 08-30-2009 05:51 PM
IanRIanR

Excellent!

 

Hint: Write another trigger, this time against the Contact object that loops through each inserted/updated Contact, and writes data to the Contact.Account object

 

(this was the point of me asking whether you were catering for changes to the Account, or the Contact)

 

 

Good work :)

 

Cheers, Ian

 

jjnhjjnh

feel like dropping some more hints as i bang my head on the wall, hehehe

 

 

 

thanks for the help, i will post back when I get further along, switching up to the contact object is throwin me off a bit. 

IanRIanR

 

Hi,

 

The Contact trigger is very similar to the Account-level one in structure: You still need to iterate through the collection of changed records and build a map of account objects that will be updated within the trigger. The difference is that the trigger is going to insert/update your Contact (or Contacts) so you will manually need to update the Account(s) yourself...

 

Should look something like this (you'll need to add in all your fields)

 

 

trigger UpdateAccountFromContact on Contact (before insert, before update) { Set<Id> accountIds = new Set<Id>(); for (Contact c : Trigger.new) { accountIds.add(c.AccountId); } Map<Id, Account> accountsToUpdate = new Map<Id, Account>([SELECT Id FROM Account where Id in: accountIds]); for (Contact c : Trigger.new) { Account a = accountsToUpdate.get(c.AccountId); a.Most_Recent_Conversion__c = c.Most_Recent_Conversion__c;

// add in other fields here.... } update accountsToUpdate.values(); }