function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
mngmng 

Validation rules using old values during account merge

So I want to merge accounts. I know that when I merge accounts, only the update and delete triggers will fire on the Winning and Losing accounts, respectively. However, I also want some triggers to fire on some objects related to Accounts when the Accounts are merged. Let's call the objects Account_Object_1 and Account_Object_2. There's nothing special about these two objects, just the following.

 

Account_Object_1:

- Notable fields:

> Account__c [ Lookup(Account) ]

 

Account_Object_2:

- Notable fields:

> Account__c [ Lookup(Account) ]

> Account_Object_1__c [ Lookup(Account_Object_1__c) ]

> Checkbox__c [ Checkbox ]

- Validation rule:

> Fail when: Account__c <> Account_Object_1__r.Account__c

 

There's a trigger sitting on Accounts. After delete, it wants to do this:

 

public static void doSomething( List<Account> deletedAccounts )
{
	Set<Id> masterAccountIds = new Set<Id>();

	for( Account account : deletedAccounts )
	{
		if( account.MasterRecordId != null )
		{
			masterAccountIds.add( account.MasterRecordId );
		}
	}

	if( !masterAccountIds.isEmpty() )
	{
		List<Account_Object_2__c> relatedObjects = [ SELECT Id Account__c, Account_Object_1__r.Account__c
FROM Account_Object_2__c
WHERE Account__c IN :masterAccountIds ]; for( Account_Object_2__c accountObject : relatedObjects ) { System.debug( accountObject.Account__c );
                 System.debug( accountObject.Account_Object_1__r.Account__c );
                 accountObject.Checkbox__c = true; } try { update relatedObjects; } catch( System.Exception ex ) { throw ex; } } }

 

It's pretty simple, but it just wants to do an Update on all the Objects, and at this point in the trigger it will pull in Account_Object_2 records that originally belonged to the Account as well as the new ones that got carried over from the merge.

 

So here's where it starts getting strange.

 

If you throw this code into an org, and merge accounts through the UI, it's going to be fine. The accounts will merge, the triggers will fire, and those checkboxes on those related records are going to populate correctly. You can test this out for yourself.

 

Aha! Gotcha! You shouldn't leave code untested! So a unit test would just involve creating a couple of each record, inserting them, and ultimately getting here.

 

Test.startTest();

	merge testMasterAccount testLoserAccount;

Test.stopTest();

 Seeing as how it supposedly works through the UI..this statement shouldn't cause a problem, right? However, surprise surprise, it fails. Why?

 

17:28:45.522|VALIDATION_RULE|03d50000000Gu6s|Sync_Rule
17:28:45.526|VALIDATION_FORMULA|Account__c <> Account_Object_1__r.Account__c|Account__c=0015000000ZgXdq , Account_Object_1__r.Account__c=0015000000ZgXdr
17:28:45.526|VALIDATION_FAIL

 

Ah, so it's that validation rule. It's saying that the field value on the Account_Object_2 record isnt the same as the one on its related record, eh? I'll just take a peek inside the trigger and take a look at what's wrong here...

 

17:28:45.509|USER_DEBUG|[21]|DEBUG|0015000000ZgXdqAAF
17:28:45.509|METHOD_EXIT|[21]|System.debug(ANY)
17:28:45.509|METHOD_ENTRY|[22]|System.debug(ANY)
17:28:45.509|USER_DEBUG|[22]|DEBUG|0015000000ZgXdqAAF

 Or not. So as you can see from the method being executed, it's making debugs right after it queries for those related objects back. There aren't any other triggers, workflows, changes happening to the object between the DML and the query, so it's not like those values are changing elsewhere. What this basically looks like is that the validation rule is using values that are not the same as what exists in the queryable context of apex, and that's just baffling.

 

So. Ideas? Thanks for reading.