+ Start a Discussion
Brandon Gittelman 2Brandon Gittelman 2 

Account Contact Relationship -- Only have 1 Primary contact able to be checked

Since our recent move to Lightning, we've lost the ability to use the Contact Roles feature on our Accounts. 

The given response from salesforce is to use the Account Contact Relationship object and add a checkbox called "Primary" (Primary__c)

This has been working well, but this unfortunetely doesn't prevent our sales reps from accidently selecting multiple primary contacts. 

I believe what I'm needing is a trigger on the AccountContactRelationship object that will prevent multiple people from being checked and display an error. 

I've found a few trigger codes that say they work, but all seem to error out when complied in my sandbox org as I don't believe they were written for the AccountContactRelationship object
Abdul KhatriAbdul Khatri
Can you please share the error you are getting?

Can you make sure Contacts to Multiple Accounts Settings is enable in your sandbox?
User-added image

Also please share the trigger code for review?
HARSHIL U PARIKHHARSHIL U PARIKH
Hello Brandon!

Here is a trigger code which might help you resolve the puzzle. I have created a custom object named AccountContactRelationship_Custom__c in order to compherend the requirement.

Here we go,

Note: You will have to put your object name in place of AccountContactRelationship_Custom__c (which is probably AccountContactRelation)
          You will have to put your field name in place of AccountId__c & ContactId__c (which is probably AccountId & ContactId accordingly)
          You will also have to flip Primary_Contact__c to your own field (which is Primary__c I believe)
Trigger PreventMultiplePrimaryContacts on AccountContactRelationship_Custom__c (Before Insert, Before Update) {
    
    List<AccountContactRelationship_Custom__c> recordsToProcess = New List<AccountContactRelationship_Custom__c>();
    List<Id> accountIds = New List<Id>();
    List<Id> contactIds = New List<Id>();
    
    
    If(Trigger.isBefore && (Trigger.IsInsert || Trigger.IsUpdate))
    {
        For(AccountContactRelationship_Custom__c EveryRelationshipRecord : Trigger.New)
        {
            If(EveryRelationshipRecord.Primary_Contact__c == TRUE)
            {
                recordsToProcess.add(EveryRelationshipRecord);
                accountIds.add(EveryRelationshipRecord.AccountId__c);
                contactIds.add(EveryRelationshipRecord.ContactId__c);
            }
        }
    }
    
    List<AccountContactRelationship_Custom__c> existingRecords = [Select id, 
                                                                         ContactId__c, 
                                                                         AccountId__c, 
                                                                         Primary_Contact__c
                                                                  FROM AccountContactRelationship_Custom__c
                                                                  WHERE Primary_Contact__c = TRUE
                                                                    AND Id !=: recordsToProcess
                                                                    AND AccountId__c =: accountIds];
                                                                    
                                                                    
        If(recordsToProcess.isEmpty())    return;
        
        For(AccountContactRelationship_Custom__c junctionObj :recordsToProcess ){
            For(AccountContactRelationship_Custom__c EveryExistingRecord : existingRecords)
            {
                If(junctionObj.AccountId__c == EveryExistingRecord.AccountId__c)
                   {
                        junctionObj.addError('There is already one Primary Contact exists for this Account');
                   }
            
            }
        }
    
    

}
Above trigger will prevent second primary contact for a account on insert and update operation.

Brandon, if this helps to solve your question then please mark it as the Best Answer!

Regards,
Harshil Parikh









 
Brandon Gittelman 2Brandon Gittelman 2
@HARSHIL PARIKH AKA:Govind

That worked in Sandbox!

However when I'm trying to push it to Prod, it's failing with 0% code coverage. 
HARSHIL U PARIKHHARSHIL U PARIKH
Brandon, in salesforce, we are required to write unit tests for our triggers, classes, controllers etc. 

Here is a test class I can offer for you to deploy the trigger. However, I would suggest you to go through the class and modify as necessary.

Here we go,
 
@IsTest
public class PreventMultiplePrimaryContacts_Test {
    
    /*
     * You can easily modify below test class for the BULK TEST by changing the integer.
     * Bulk testing is the best practice on force.com.
     */
    
    final static Integer AccountsToInsert = 1;
    final static Integer ContactsPerAccountToInsert = 1;
    
    @TestSetUp
    Public static void CreatingData()
    {
        DataFactory(AccountsToInsert, ContactsPerAccountToInsert);
    }
    
    
    // Test Method
    Public static TestMethod void OnlyOnePrimaryContactAllowed()
    {    
        // First we will insert one primary contact per each account.
        List<AccountContactRelationship_Custom__c> junctionObjRecordsToInsert = New List<AccountContactRelationship_Custom__c>();
        For(Account EveryAccount : [Select Id, (Select id FROM Contacts LIMIT 1) FROM Account])
        {
            AccountContactRelationship_Custom__c junctionObjRecord = New AccountContactRelationship_Custom__c();
            junctionObjRecord.accountId__c = EveryAccount.Id;
            junctionObjRecord.ContactId__c = EveryAccount.Contacts[0].id;
            junctionObjRecord.Primary_Contact__c = TRUE;
            junctionObjRecordsToInsert.add(junctionObjRecord);
        }
        Database.insert(junctionObjRecordsToInsert, TRUE);
        
        // At this point, each account should have one primary contact record. Let's assert:
        For(Account actWithPrimaryCon : [Select Id, 
                                         		(Select id, Primary_Contact__c FROM AccountContactRelationship_Custom__r LIMIT 1)
                                        	FROM Account])
        {
            system.assertEquals(1, actWithPrimaryCon.AccountContactRelationship_Custom__r.size());
            system.assertEquals(TRUE, actWithPrimaryCon.AccountContactRelationship_Custom__r[0].Primary_Contact__c);  
        }
        
        
        // Now we will enter another set of primary contact for an account and that should be blocked.
        List<AccountContactRelationship_Custom__c> junctionObjToInsert = New List<AccountContactRelationship_Custom__c>();
        For(Account EveryAccount : [Select Id, (Select Id FROM Contacts) FROM Account])
        {
            AccountContactRelationship_Custom__c junctionObj = New AccountContactRelationship_Custom__c();
            junctionObj.AccountId__c = EveryAccount.Id;
            junctionObj.ContactId__c = EveryAccount.Contacts[0].Id;
            junctionObj.Primary_Contact__c = TRUE;
            junctionObjToInsert.add(junctionObj);
        }
        
        For(AccountContactRelationship_Custom__c EveryJunctionObj : junctionObjToInsert){
            try{
                Insert EveryJunctionObj;
            }catch(DMLException dEX){
                // This makes sures that the second Primary contact on account is not allowed. 
                system.assert(dEX.getMessage().contains('There is already one Primary Contact exists for this Account'));
            }
        }
        
    }
    
    // Data Factory Method
    Public static void DataFactory(Integer totalAccounts, Integer totalContactsPerAccount)
    {
        // Creating an Account Records
        List<Account> actListToinsert = New List<Account>();
        For(Integer a = 0; a < totalAccounts; a++)
        {
            Account act = New Account();
            act.Name = 'My Custom Account: ' + string.valueOf(a);
            actListToinsert.add(act);
        }
        Database.insert(actListToinsert, TRUE);
        
        // Creating Contact records per each account
        List<Contact> contactListToInsert = New List<Contact>();
        For(Account EveryAccount : actListToinsert)
        {
            For(Integer c = 0; c < totalContactsPerAccount; c++)
            {
                Contact con = New Contact();
                con.LastName = 'Custom Last Name: ' + string.valueOf(c);
                con.AccountId = EveryAccount.Id;
                contactListToInsert.add(con);
            }
        }
        Database.insert(contactListToInsert, TRUE);

    }
}

I have tested an above test class and its giving 100 code coverage to below trigger I have mentioned in above post:
 
Trigger PreventMultiplePrimaryContacts on AccountContactRelationship_Custom__c (Before Insert, Before Update) {
    
    List<AccountContactRelationship_Custom__c> recordsToProcess = New List<AccountContactRelationship_Custom__c>();
    List<Id> accountIds = New List<Id>();
    List<Id> contactIds = New List<Id>();
    
    
    If(Trigger.isBefore && (Trigger.IsInsert || Trigger.IsUpdate))
    {
        For(AccountContactRelationship_Custom__c EveryRelationshipRecord : Trigger.New)
        {
            If(EveryRelationshipRecord.Primary_Contact__c == TRUE)
            {
                recordsToProcess.add(EveryRelationshipRecord);
                accountIds.add(EveryRelationshipRecord.AccountId__c);
                contactIds.add(EveryRelationshipRecord.ContactId__c);
            }
        }
    }
    
    List<AccountContactRelationship_Custom__c> existingRecords = [Select id, 
                                                                         ContactId__c, 
                                                                         AccountId__c, 
                                                                         Primary_Contact__c
                                                                  FROM AccountContactRelationship_Custom__c
                                                                  WHERE Primary_Contact__c = TRUE
                                                                    AND Id !=: recordsToProcess
                                                                    AND AccountId__c =: accountIds];
                                                                    
                                                                    
        If(recordsToProcess.isEmpty())    return;
        
        For(AccountContactRelationship_Custom__c junctionObj :recordsToProcess ){
            For(AccountContactRelationship_Custom__c EveryExistingRecord : existingRecords)
            {
                If(junctionObj.AccountId__c == EveryExistingRecord.AccountId__c)
                   {
                        junctionObj.addError('There is already one Primary Contact exists for this Account');
                   }
            
            }
        }
    
    

}

Hope this helps. If it resolves your query, please mark it Best Answer!

Thank you.
Harshil Parikh