Salesforce Communities: Enable Partners To Remove

Salesforce introduces Communities, addressing the much-needed improvement in the outdated partner portal user interface. Having participated in the pre-release, I discovered both positive and negative aspects of the new functionality. One significant drawback is the absence of the ability for Community Users to delete records. While Salesforce.com presented a comprehensive list of reasons justifying the exclusion of this basic functionality, the practicality of partners having to rely on administrators for record removal seemed impractical.

After enduring a week of handling deletion requests during the pilot, I took the initiative to make the functionality accessible to Community Users, aiming to alleviate frustration for both parties. At a technical level, this involves creating a Visualforce page, a corresponding controller, and a custom button that can be integrated into Community page layouts.

While this functionality can be implemented for any object accessible to a specific group of Community Users, I will provide the code specifically for the Opportunity object for simplicity and ease of integration. To begin, let’s create a controller for the Visualforce page. The code for the controller is outlined below:

/*
	Created by: Greg Hacic
	Last Update: 3 June 2013 by Greg Hacic
	Questions?: greg@interactiveties.com
*/
public class deleteOpportunityController {
	
	private final Opportunity opp; //Opportunity object
	
	public deleteOpportunityController(ApexPages.StandardController standardPageController) {
		this.opp = (Opportunity)standardPageController.getRecord(); //instantiate the opp object for the current record
	}
	
	//method called from the Visualforce's action attribute
	public PageReference deleteThisOpportunity() {
		List<Opportunity> opportunitiesToDelete = new List<Opportunity>(); //list for holding updated records
		Opportunity opportunityToDelete = new Opportunity(Id = opp.Id); //set the object that we want to update
		opportunitiesToDelete.add(opportunityToDelete); //add the updated Opportunity to out list
		if (!opportunitiesToDelete.isEmpty()) { //if there is an update to process
			delete opportunitiesToDelete;
		}
		PageReference pageWhereWeEndUp = new PageReference('/YourCommunityName/006/o'); //set the return page reference to the Opportunity tab
		return pageWhereWeEndUp.setRedirect(true); //send the User on their way
	}

}

Those who are not acquainted with the recent Communities functionality should be aware that adjustments need to be made to the code on line 22 (‘/YourCommunityName/006/o’) according to the specific name of your community. Simply replace “YourCommunityName” with the actual name of your community.

As a side note, I strongly believe that salesforce.com should consider revising the URLs employed for communities, as managing code across multiple communities within a single organization can be quite cumbersome. Just my two cents…

Moving forward, we require the Visualforce page that will enable the execution of the aforementioned code. The page is provided below:

<!--
	Created by: Greg Hacic
	Last Update: 3 June 2013 by Greg Hacic
	Questions?: greg@interactiveties.com
-->
<apex:page standardController="Opportunity" extensions="deleteOpportunityController" action="{!deleteThisOpportunity}">
	<apex:pageMessages></apex:pageMessages>
	<apex:detail relatedList="true"></apex:detail>
</apex:page>

Certainly, the page may appear overly simplified, but this is intentional as, in an ideal scenario, users should not directly encounter this page. Instead, they will be seamlessly redirected to this page and subsequently redirected (again) to the Opportunity tab once the deletion logic successfully concludes. Nevertheless, this Visualforce page serves as a means to display error messages to users in the event of any unforeseen errors or issues.

The final component required is the button setup. We will create a new button labeled “Delete,” which will be included in the page layouts visible to Community Users. To access custom buttons on the Opportunity object, follow this click stream: Setup > Customize (under ‘App Setup’) > Opportunities > Buttons and Links. On the resulting page, you’ll find a list of standard Opportunity buttons, any overrides, and a section displaying custom buttons and links. Scroll down to the “Custom Buttons and Links” section and click the “New” button.

On the subsequent page, you can specify how you want the button to be displayed on the page and its functionality when clicked. Provide a “Label” for your button, representing the text displayed on the button in the page layout. After tabbing or clicking out of this field, Salesforce should auto-populate the “Name” field. Choose “Display Type” as “Detail Button.” For “Behavior,” select “Execute JavaScript,” and for “Content Source,” choose “OnClick JavaScript.” Refer to the screenshot below for an illustration of this configuration.

The actual Javascript for the button is as follows:

/*
    Created by: Greg Hacic
    Last Update: 31 January 2024 by Ayub Ansari
    Questions?: greg@ayub@tenetizer.com
*/
var confirmDeletion = confirm("Are you sure you want to delete this record?"); //prompt the User for confirmation that they truly want to delete this record
if (confirmDeletion == true) { //if they confirm the deletion
    parent.location.href = '/YourCommunityName/apex/deleteOpportunity?id={!Opportunity.Id}'; //send them to the Visualforce page where we will run the deletion logic
}}

Exercise caution in this step, as it’s crucial to incorporate your Community name in this JavaScript. On line 8, eliminate the “YourCommunityName” string and substitute it with your actual Community name. Additionally, if you named your Visualforce page something other than “deleteOpportunity,” make sure to modify that string on line 8 accordingly.

While code proves its utility when it includes sufficient test coverage, ensuring its practicality for other developers. Therefore, here is that integral piece of the puzzle:

/*
	Created by: Ayub Ansari
	Last Update: 31 January 2024 by Ayub Ansari
	Questions?: greg@ayub@tenetizer.com
*/
@isTest
private class deleteOpportunityControllerTEST {
	
	static testMethod void successLogic() {
		//BEGIN: perform some setup steps...
		List<Account> accounts = new List<Account>();
		accounts.add(new Account(Name = 'Interactive Ties', Website = 'http://www.interactiveties.com/'));
		insert accounts;
		List<Opportunity> opportunities = new List<Opportunity>();
		opportunities.add(new Opportunity(AccountId = accounts[0].Id, Amount = 200000, CloseDate = date.today(), Name = 'iTies Test Opportunity', StageName = 'Identified'));
		insert opportunities;
		//END: perform some setup steps...
		Test.startTest();
		PageReference visualForcePage = new PageReference('/apex/deleteOpportunity?id='+opportunities[0].Id);
		Test.setCurrentPage(visualForcePage);
		ApexPages.StandardController standard_controller = new ApexPages.standardController(new Opportunity(Id = opportunities[0].Id));
		deleteOpportunityController extVisualForcePage = new deleteOpportunityController(standard_controller);
		String validationURLString = extVisualForcePage.deleteThisOpportunity().getURL();
		System.assertEquals(true, validationURLString.contains('/006/o'));
		Test.stopTest();
	}

}

I refrained from commenting on the test logic, but feel free to reach out if you have any questions. If I receive numerous inquiries, I might consider adding comments to the code. I’m just feeling a bit lazy this evening…

So, there you have the code for enabling record deletions by Community Users. In my view, Community Users should have the ability to delete records. However, until salesforce.com shares this sentiment, you can use this as a viable option to grant such permissions. Keep in mind that you’ll need to code a variation of this solution for each object, which is admittedly cumbersome.Honestly, I didn’t anticipate that salesforce.com would endorse this kind of workaround, but I’m pleased they do because (did I mention) allowing partners to delete certain records significantly reduces headaches.