Communicate Merged Records to Systems using Platform Events and Change Data Capture

Author: Bruce Tollefson Published: July 26, 2021; Modified: May 9, 2022
connected_dots

In Salesforce merging a record itself is simple; one record is deleted(the loser), one record is updated(the winner), and the children are reparented. With CDC that is all out of the box. If the external system and any processes can handle those operations alone then it is all straight forward and easy to implement. However, what if an external system needs to know when a record is being merged and not just updated/deleted? Then it gets a little more complex, where we will need to create an additional platform event as Change Data Capture will not indicate the 2 records have been merged.

When merging records from the UI there is no clear operation to identify the merge occurred. The events that occur are the update(winning record) and delete(losing record) events, stated here. When the losing record is deleted it is updated during the ‘After Delete’ with the ‘MasterRecordId’. This provides us with the ability to identify the merged record winner and loser.

Setup

To view everything that happens we are going to create the following Account trigger:

trigger AccountTrigger on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) { try{ for(Account act :Trigger.New){ system.debug(Trigger.operationType); system.debug(JSON.serializePretty(act)); } }catch(Exception e){} try{ for(Account act :Trigger.Old){ system.debug(Trigger.operationType); system.debug(JSON.serializePretty(act)); } }catch(Exception e){} }

Add the emp-api lightning web component previously created.

Go to setup –> Change Data Capture and add Account and Contact. We will be creating 2 accounts, 1 contact, then merging and see what occurs.

Investigate Change Data Capture with Merged Records

Now we will look at the CDC events. Go to the LWC event listener we created and subscribe to ‘/data/ChangeEvents’. In dev console execute the following in anonymous to create 2 accounts:

// Insert new accounts List ls = new List{ new Account(name='Acme Inc.'), new Account(name='Acme') }; insert ls;

Then create a contact:

//query mergedAccount Account mergeAcct = [SELECT Id, Name FROM Account WHERE Name = 'Acme' LIMIT 1]; // Add a contact to the account to be merged Contact c = new Contact(FirstName='Joe',LastName='Merged'); c.AccountId = mergeAcct.Id; insert c;

Now merge:

// Queries to get the inserted accounts Account masterAcct = [SELECT Id, Name FROM Account WHERE Name = 'Acme Inc.' LIMIT 1]; Account mergeAcct = [SELECT Id, Name FROM Account WHERE Name = 'Acme' LIMIT 1]; try { merge masterAcct mergeAcct; } catch (DmlException e) { // Process exception System.debug('An unexpected error has occurred: ' + e.getMessage()); }

When looking at the feed you will see the account and contact records created. The winning account being updated, the losing account being deleted (notice there are no details in the detail, this can be an issue if the downstream system needs to know about the merge), and the contact record being updated to the new parent.

Investigate the Account Trigger

The above apex needed to occur in multiple transactions to see the full picture, due to the messages being created after the transaction has been finalized. To look at the trigger execute the following in dev console anonymous:

// Insert new accounts List ls = new List{ new Account(name='Acme Inc.'), new Account(name='Acme') }; insert ls; // Queries to get the inserted accounts Account masterAcct = [SELECT Id, Name FROM Account WHERE Name = 'Acme Inc.' LIMIT 1]; Account mergeAcct = [SELECT Id, Name FROM Account WHERE Name = 'Acme' LIMIT 1]; // Add a contact to the account to be merged Contact c = new Contact(FirstName='Joe',LastName='Merged'); c.AccountId = mergeAcct.Id; insert c; try { merge masterAcct mergeAcct; } catch (DmlException e) { // Process exception System.debug('An unexpected error has occurred: ' + e.getMessage()); }

Then look at the dev console log and filter on the debug. Here you will see again the accounts(we didn’t add a trigger on the contact as it will so the same thing as the listener) being created and updated with one difference. On the ‘After Delete’ the losing merged record will have the ‘MasterRecordId’ populated.

Know this is the only time when we can truly identify a merged record and get both the winning and losing record. We can create a trigger on the account ‘After Delete’ to look up the winner(use the MasterRecordId if you need to query anything on the winning record) and the loser. And create a platform event to send any data for the external system.

Merged Record Platform Event

As an example we will send a platform event with the winning and losing Salesforce Ids. Create a platform event ‘Setup’ –> ‘Platform Events’: Merged_Account__e with 2 text fields Winning_Account_Id__c and Losing_Account_Id__c.

Update the account trigger to:

trigger AccountTrigger on Account (after delete) { List mergedAcctList = new List(); for(Account acct :Trigger.Old){ if(acct.MasterRecordId != null){ Merged_Account__e mergedAcct = new Merged_Account__e( Losing_Account_Id__c = acct.Id, Winning_Account_Id__c = acct.MasterRecordId ); mergedAcctList.add(mergedAcct); } } //publish List results = EventBus.publish(mergedAcctList); for (Database.SaveResult sr : results) { if (sr.isSuccess()) { System.debug('Successfully published event.'); } else { for(Database.Error err : sr.getErrors()) { System.debug('Error returned: ' + err.getStatusCode() + ' - ' + err.getMessage()); } } } }

Subscribe to the event channel: ‘/event/Merged_Account__e’ and fire the anonymous apex again to merge the accounts. In the listener LWC you will see the newly created Merged Account platform event message with the winning and losing Ids.

One comment on “Communicate Merged Records to Systems using Platform Events and Change Data Capture”

  • JosephHen says:

    You have hit the mark.

  • Leave a Reply

    Your email address will not be published. Required fields are marked *