I presented the following solution at Dreamforce 16 at the MVP Process Automation Smackdown, ER, I mean MVP Process Automation Showdown. This was a friendly competition with my fellow automation guru MVPs, Rakesh Gupta, Mike Gill and Chris Edwards.
Here is a link to our presentation slide show and YouTube recording, which includes embedded demo videos of each of our creative process automation ideas: Presentation | YouTube Recording
The audience voted and the one with the most votes won…and that was ME!
When you delete a Salesforce record that has related records via a lookup relationship, the related records are not deleted. Only related records that have a master-detail relationship will be deleted when the master record is deleted. When the parent record is deleted, the relationship that these child records had via a lookup relationship is broken. Identifying these child records for cleanup purposes may become difficult after the parent record is deleted. Ideally, when the parent record is deleted, these child records via the lookup relationship should also be deleted.
Here are a few lessons learned from implementing this use case:
- Strengthen your flow from faulting by adding decision elements.
- Provide descriptions, where provided, in Salesforce. This may be tedious step, I know, but your future self will thank you when you are trying to remember what you configured or assist other/future admins when troubleshooting or enhancing what was built. This includes noting the data stored in a custom field, providing the purpose of a process builder, etc.
Business Use Case: Addison Dogster is a system administrator at Universal Container. Sally Sunshine is the Sales Manager. Sally needs the ability to indicate that a contact as inactive. She also wants to delete these inactive contacts and their related case records. One caveat, the contact and its related records must stay intact for reporting purposes for the calendar year. After the calendar year, the records can be deleted on January 1 of the following year.
Solution: While this can be handled via a trigger, Addison Dogster, being the Awesome Admin that she is, was able to solve this using two custom fields, process builder and visual workflow. She can do this with clicks, no code!
Quick Steps:
1.Create a custom picklist field called “Status” to the Contact object with the picklist values “Active” (set as the default) and “Inactive.” For those using Salesforce Classic, you can create custom fields by going to Setup | Customize | Contact. In Lightning Experience, it is found under Objects and Fields |Object Manager | Contact | Fields and Relationships.
Best practice tips:
- Don’t forget to provide a description so you and other/future admins know what this custom field is used for.
- Set the FLS (field level security) for each profile. Only make the field visible and editable for the profiles that need it. Do not just click the “Next” button when you are on the screen.
The end result is this…
2. Create a custom date field called “Deletion Date” to the Contact object. For those using Salesforce Classic, you can create custom fields by going to Setup | Customize | Contact. In Lightning Experience, it is found under Objects and Fields |Object Manager | Contact | Fields and Relationships.
Best practice tips:
- Don’t forget to provide a description so you and other/future admins know what this custom field is used for.
- Set the FLS (field level security) for each profile. Only make the field visible and editable for the profiles that need it. Do not just click the “Next” button when you are on the screen.
- Since this is a processing field, you do not need to place this on the page layout.
This is the end result…
3. Let’s create the flow. For those using Salesforce Classic, flow can be found in Create | Workflows & Approvals | Flows. In Lightning Experience, it is found under Process Automation | Flows.
A. Create the following flow elements by going to the Resources tab in flow.
Create a variable called “varContactID”:
Create a SObject Collection variable called “CollectionofCases”:
Best practice tip: Provide a description so you and other/future admins know what this variable is used for.
B. Create a Fast Lookup flow element to perform a lookup of related cases in the Case object where the ContactID equals the value in the variable varContactID that is passed from the Process Builder we will build in Step 3. If case records are found, the records are stored in a sObject variable collection called “CollectionofCases.” Check the box next to “Assign null to the variable if no records are found.”
(Note: we are using Fast Lookup instead of Record Lookup because we expect to return a collection of cases in our lookup, not just one record.)
Best practice tip: Provide a description so you and other/future admins know what this variable is used for.
C. In the next step, we will perform a decision to determine whether any case records were found in the previous step. We cannot assume that there will always be related cases associated to an inactive contact. We don’t want to send the flow down a path where it will try and delete related cases when none exist. That would cause the flow to fail. Let’s add a Decision flow element called “Cases Found” where the Decision “Cases Found in Lookup” has the criteria: {!CollectionofCases} is null {!GlobalConstant.False}. Essentially here, we want to see if the variable has values (is not null). Set the default outcome to “No Cases.”
Best practice tip: Provide a description so you and other/future admins know what this variable is used for
D. If cases are found, we want to delete the related cases. Let’s create a Fast Delete flow element to delete the records in the sObject collection variable CollectionofCases. (Note: we are using Fast Delete instead of Record Delete because we expect a collection of cases to delete, not just one record.)
Best practice tip: Provide a description so you and other/future admins know what this variable is used for.
E. Lastly, we need to delete the inactive contact. Here, we need to create a Record Delete flow element on the Contact object where the ContactID equals the variable varContactID.
Best practice tip: Provide a description so you and other/future admins know what this variable is used for.
F. Now, we need to set the Fast Lookup as a starting element, indicated by the green down arrow. Then, connect the flow elements by looking at the yellow highlighted connectors. The “Cases Found in Lookup” decision will point to the Fast Delete so the related cases can be deleted. The “No Cases” default outcome decision will point to the Record Delete flow element since there are no related cases to delete. We need to connect the Fast Delete flow element to the Record Delete flow element so that we can delete the inactive contact after we delete the related cases.
G. For the ease of a quick process automation solution for use during Dreamforce, this solution does not include my usual fault email flow elements that my flow solutions normally have. Please refer to my post “Maximize Maintainability with Process Builder and Componentized Visual Workflow, Step 2″ Connect fault connectors from the Fast Lookup, Fast Delete and Record Delete flow elements to the Send Fault Flow Email subflow.
H. Save as and provide the following properties. Make sure the type is set to Autolaunched Flow because we will be using Process Builder to invoke the flow. I include in my descriptions the name of the process builder a flow is invoked in, helps in troubleshooting down the road.
Best practice tip: Provide a description so you and other/future admins know what this variable is used for.
I. Click the “Close” button.
J. On the flows screen, activate the flow.
3. Now, let’s create the process builder for the Contact object.
For those using Salesforce Classic, process builder can be found in Create | Workflows & Approvals | Process Builder. In Lightning Experience, it is found under Process Automation | Process Builder.
Let’s name this “Delete Case(s) & Contact When Contact is Inactive”, description and select “A record changes” under the option “The process starts when” and click the “Save” button.
Best practice tips: Don’t forget to provide a description so you and other/future admins know what this process builder is used for.
A. Select “Contact” as the object. Select to start the process “when a record is created or edited” and click the “Save” button.
B. There is only one node criteria. We’re going to call it “Status is Inactive” where the condition is [Coontact].Status__c Equals Picklist Inactive.
We have one immediate action.
Action Type: Update Records
Action Name: Update Deletion Date
Record Type: Select the Contact record that started your process
We will set the Deletion Date field using a formula: DATE(YEAR (DATEVALUE([Contact].LastModifiedDate))+1, 1, 1) [This essentially takes the contact’s last modified date and sets the value to January 1 of the following year.]
The end result looks like this…
There is one scheduled action…We want this to execute 0 days after the deletion date, we want to invoke the visual workflow we created in Step 2 to delete all related cases and the inactive contact record.
The end result looks like this…
Now, for the scheduled action, we want to invoke the flow.
Action Type: Flows
Action Name: InvokeFlow
Flow: Delete Cases and a Contact
Set Flow Variables: varContactID Reference [Contact].Id
The end result looks like this…
Now, you are ready to activate your process builder. Click on the “Activate” button.
That’s it! Congrats! You’ve implemented a process to automate the process of deleting a record and related case records that have a lookup relationship to it.
Deployment Notes/Tips:
- The new custom fields, process builder and visual workflow can be deployed to Production in a change set (or can be deployed using a tool such as Dreamfactory’s Snapshot).
- The field level security for the custom status and deletion date fields will need to be manually updated post deployment. I would caution against adding the related profiles in the changeset for deployment as the results of deploying a profile are not reliable. If you have a tool like Snapshot by Dreamfactory, you can use the tool to deploy field permissions.
- Activate the process builder and visual workflow as they are deployed as inactive into Production.
As part of step 3, you have set up process builder with “Contact” as the object and selected “when a record is created or edited” to start the process. Then how it is possible to invoke flow using scheduled action as ‘Scheduled Action’ only possible when process chosen to start “when record is created”?
LikeLike
In the criteria node screen, make sure you check the option “Do you want to execute the actions only when specified changes are made to the record?” This will allow the scheduled actions to show. I corrected the blog post image.
LikeLike