Update to Partner Contact by Community User

Businesses that utilize Salesforce Communities for partners instead of the standard partner portal may find that partners have the ability to search for and find the Contact record that corresponds to their Community User record. It would be nice if salesforce.com did not allow for this visibility because the Partner User is technically unable to make updates to the Partner Contact record. If they click the "Edit" button for the Contact they will receive the Insufficient Privileges message. However, Community Users are permitted to make updates to their own User record by clicking the "Edit Contact Info" link from the upper right-hand side of the navigation bar.

Often a partner will call for support when the Partner Contact information is inaccurate and ask "why can't I edit that myself?"

Since this seemed like a reasonable request, I thought that I would write an Apex Trigger to allow for User record updates to get passed to the corresponding Partner Contact record when applicable. This made support for these partner requests easier because we could simply tell the partner to edit their own information via the "Edit Contact Info" link and let them know that the changes would systemically pass to the partner contact record that they might see in search results within the Salesforce Community.

Below you will find all of the logic for implementing this functionality within your Salesforce org.

The Apex trigger:

/*
	Created by: Greg Hacic
	Last Update: 28 July 2014 by Greg Hacic
	Questions?: greg@interactiveties.com
	
	Notes:
		- Testing methods located: updateContactWhenPortalUpdateTest.cls
*/
trigger updateContactFromCommunities on User (after update) {
	
	if (Trigger.new.size() == 1 && !System.isFuture()) { //only run the logic when the trigger is fired from a single update and the update is not being fired from a future method
		User u = Trigger.new[0]; //grab the User sObject
		if (u.ContactId != null) { //make sure there is an associated Contact
			updateContactWhenPortalUpdate.updateContact(u.Id); //call the future method
		}
	}

}

The Apex future method for handling the update of the Contact record based upon the details provided by the corresponding User record:

/*
	Created by: Greg Hacic
	Last Update: 28 July 2014 by Greg Hacic
	Questions?: greg@interactiveties.com
	
	Notes:
		- Testing methods located: updateContactWhenPortalUpdateTest.cls
*/
global class updateContactWhenPortalUpdate {
	
	@future
	public static void updateContact(String userId) {
		User u = [SELECT City, ContactId, Country, Email, FirstName, LastName, Phone, PostalCode, State, Street, Title FROM User WHERE Id = :userId]; //query for the User details
		if (u != null) { //if there is a query result
			if (u.ContactId != null) { //if there is an associated Contact
				//provide all of the User details for the Contact update
				Contact c = new Contact(Id = u.ContactId);
				c.Email = u.Email;
				c.FirstName = u.FirstName;
				c.LastName = u.LastName;
				c.MailingCity = u.City;
				c.MailingCountry = u.Country;
				c.MailingPostalCode = u.PostalCode;
				c.MailingState = u.State;
				c.MailingStreet = u.Street;
				c.Phone = u.Phone;
				c.Title = u.Title;
				update c; //update the contact record
			}
		}
	}

}

The Apex test coverage:

/*
	Created by: Greg Hacic
	Last Update: 28 July 2014 by Greg Hacic
	Questions?: greg@interactiveties.com
	
	Notes:
		- Tests for updateContactWhenPortalUpdate.class (100% coverage)
		- Tests for updateContactFromCommunities.trigger (100% coverage)
*/
@isTest
private class updateContactWhenPortalUpdateTest {
	
	@isTest //defines method for use during testing only
	static void updateContactInfo() {
		//BEGIN: some setup items
		Profile randomProfile = [SELECT Id FROM Profile WHERE UserType = 'PowerPartner' LIMIT 1];
		//create accounts for our portal users
		List partnerAccounts = new List();
		partnerAccounts.add(new Account(Name = 'Testing Communities Company'));
		insert partnerAccounts;
		//Create some Contacts because we want to create portal users we are required to provide a corresponding contactId
		List partnerContacts = new List();
		partnerContacts.add(new Contact(AccountId = partnerAccounts[0].Id, Email = 'communitiesupdateduser@interactiveties.com', FirstName = 'Demo1', LastName = 'User1'));
		insert partnerContacts;
		List newUsers = new List();
		newUsers.add(new User(Alias = 'test01', ContactId = partnerContacts[0].Id, Email = 'communitiesupdateduser@interactiveties.com', EmailEncodingKey = 'ISO-8859-1', FirstName = 'Demo1', Group_Name__c = 'System', IsActive = true, LanguageLocaleKey = 'en_US', LastName = 'User1', LocaleSidKey = 'en_US', MobilePhone = '(303) 555-0000', Phone = '(303) 555-2222', ProfileId = randomProfile.Id, TimeZoneSidKey = 'America/New_York', Username = 'communitiesupdateduser@interactiveties.com'));
		insert newUsers;
		//END: some setup items
		//validate the initial contact information
		Contact c = [SELECT Email, FirstName, LastName, MailingCity, MailingCountry, MailingPostalCode, MailingState, MailingStreet, Phone, Title FROM Contact WHERE Id =: partnerContacts[0].Id];
		System.assertEquals('communitiesupdateduser@lm2network.com', c.Email);
		System.assertEquals('Demo1', c.FirstName);
		System.assertEquals('User1', c.LastName);
		System.assertEquals(null, c.MailingCity);
		System.assertEquals(null, c.MailingCountry);
		System.assertEquals(null, c.MailingPostalCode);
		System.assertEquals(null, c.MailingState);
		System.assertEquals(null, c.MailingStreet);
		System.assertEquals(null, c.Phone);
		System.assertEquals(null, c.Title);
		//perform the test
		Test.startTest();
		System.runAs ( new User(Id = newUsers[0].Id) ) { //runAs in order to avoid MIXED_DML_OPERATION error
			List userUpdates = new List();
			userUpdates.add(new User(City = 'San Francisco', Country = 'US', FirstName = 'Tess', Id = newUsers[0].Id, LastName = 'Hacic', PostalCode = '94105', State = 'CA', Street = 'One Market Street', Title = 'CEO'));
			update userUpdates;
		}
		Test.stopTest();
		//validate that it worked as intended
		c = [SELECT Email, FirstName, LastName, MailingCity, MailingCountry, MailingPostalCode, MailingState, MailingStreet, Phone, Title FROM Contact WHERE Id =: partnerContacts[0].Id];
		System.assertEquals('communitiesupdateduser@interactiveties.com', c.Email);
		System.assertEquals('San Francisco', c.MailingCity);
		System.assertEquals('US', c.MailingCountry);
		System.assertEquals('94105', c.MailingPostalCode);
		System.assertEquals('CA', c.MailingState);
		System.assertEquals('One Market Street', c.MailingStreet);
		System.assertEquals('CEO', c.Title);
	}

}

Thanks for reading.

Automated Exchange Rates in Salesforce.com

Reduce Repetitive Tasks, Eliminate Errors & Free Up Your Administrators.

Birthday Reminders for Salesforce.com

It might lead to a sale. Or it might make you feel good.