I have a custom field on my AccountContactRelation object, called SurrogateId__c, that has to be unique across all AccountContactRelation. I have the following code that is called upon before insert of an AccountContactRelation:
public static void attachAccountAndContact(List<AccountContactRelation> accountContactRelations) {
List<AccountContactRelation> existingRelationships = (new AccountContactRelationsSelector()).selectRelatedContactsByAccountId(AccountHelper.getAccountIdSet(accountContactRelations));
Map<Id, Map<Id, AccountContactRelation>> existingAccountContactToRelation = accountIdContactIdToRelation(existingRelationships); // maps account -> contact -> accountcontactrelation
List<AccountContactRelation> relationsToUpdate = new List<AccountContactRelation>{};
for(AccountContactRelation accountContactRelation: accountContactRelations){
Id accountId = accountContactRelation.AccountId;
Id contactId = accountContactRelation.ContactId;
if (existingAccountContactToRelation.keySet().contains(accountId) && existingAccountContactToRelation.get(accountId).keySet().contains(contactId)) {
accountContactRelation.addError('Contact ' + contactId + ' is already connected to account ' + accountId);
AccountContactRelation existingRelation = existingAccountContactToRelation.get(account.Id).get(contact.Id);
existingRelation.SurrogateId__c = accountContactRelation.SurrogateId__c;
relationsToUpdate.add(existingRelation);
}
}
if (relationsToUpdate.size() > 0) {
Database.update(relationsToUpdate);
}
}
Basically I try to update the existing AccountContactRelation with a - potentially - new surrogate id. I add an error to the record being inserted to skip it as the relationship is already there.
I'm running the following test:
private static void accountRelationAvoidInsertIfAlreadyExists() {
Account account = new Account(Name = 'Example company');
insert(account);
Contact contact = new Contact(FirstName = 'John', LastName = 'Smith', AccountId = account.Id); // note that at this point a trigger on the user sets the SurrogateId as JohnSmith
upsert(contact);
AccountContactRelation relation1 = new AccountContactRelation(SurrogateId__c = 'AnotherSurrogateKey');
Database.Insert(relation1, false);
List<AccountContactRelation> checkRelations = [SELECT Id, SurrogateId__c, Account.Name, Contact.FirstName, Login_email__c from AccountContactRelation WHERE AccountId =: account.Id];
System.assertEquals(1, relations1.size());
System.assertEquals('AnotherSurrogateKey', relations1.get(0).SurrogateId__c);
}
First test passes - that suggests that as intended, there's no additional relationship added between contact and account. However, the second test fails. It looks like the update at the end of the code was rollbacked - as SurrogateId__c at the end of the test is JohnSmith, as in the beginning of the test, and not AnotherSurrogateKey as I would expect.
Note that debugging the code, I can be sure that the update is executed (I tried to select the updated AccountContactRelations right after the Database.update, and indeed it works. As soon as I arrive at the end of the test, however, any change was rolled back).
Any idea about what is going on? Why is the update rolled back? In my understanding the addError should allow me to skip the insertion of that record and it should not trigger any rollback.
Is there any other way to do what I'm trying to do - so on before insert skip the creation of a record but update the existing one?