Modification Of Partner Contact by Community User

Businesses using Salesforce Communities for partners, as opposed to the standard partner portal, may observe that partners possess the capability to search for and locate the Contact record linked to their Community User record. Ideally, Salesforce would restrict this visibility, considering that the Partner User lacks the technical ability to update the Partner Contact record. Clicking the “Edit” button for the Contact triggers the display of the “Insufficient Privileges” message. However, Community Users are allowed to update their own User record by selecting the “Edit Contact Info” link from the upper right-hand side of the navigation bar.

Frequently, partners seek support when encountering inaccuracies in Partner Contact information and inquire, “Why can’t I edit that myself?”

Given the reasonable nature of this request, I decided to develop an Apex Trigger to facilitate the passage of User record updates to the corresponding Partner Contact record when applicable. This streamlined support for partner requests, as we could instruct partners to edit their information via the “Edit Contact Info” link, ensuring that the changes would automatically propagate to the Partner Contact record visible in search results within the Salesforce Community.

Below, you’ll find the complete logic for implementing this functionality in 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.class
*/
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 responsible for managing the update of the Contact record based on 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.class
*/
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 {
	
	static testMethod 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);
	}

}

Appreciate your time and attention.