Apex Triggers - 17 (Deloitte Interview Question)
1. Scenario Overview
This automation solves a Deloitte Interview Question focused on enforcing data integrity across parent-child relationships . The contact object features a custom checkbox field,
Primary_Contact__c . The requirement mandates that each Account can have at most one primary contact . If a user tries to create or update a contact to be a duplicate primary contact under the same account—or re-parents an existing primary contact to an account that already contains one—the transaction must block and throw an error . Because data validation must block execution before commit phases, these criteria execute entirely in
before insert and before update context steps .or
Enforce a single Primary Contact on an Account.
2. Apex Handler Class
java
public class ContactTriggerHandler {
public static void preventDuplicatePrimaryContacts(List<Contact> newContacts, Map<Id, Contact> oldContactMap) {
Set<Id> accountIds = new Set<Id>();
// Collect targeted parent account IDs across insert, update, and re-parenting events
if (newContacts != null) {
for (Contact con : newContacts) {
if (con.AccountId != null) {
if (oldContactMap == null) {
// Insert Context: Track account if contact is marked primary
if (con.Primary_Contact__c == true) {
accountIds.add(con.AccountId);
}
} else {
// Update Context: Track accounts for changes in primary status or parent accounts
Contact oldCon = oldContactMap.get(con.Id);
if (con.Primary_Contact__c == true || oldCon.Primary_Contact__c == true) {
accountIds.add(con.AccountId);
if (oldCon.AccountId != null && con.AccountId != oldCon.AccountId) {
accountIds.add(oldCon.AccountId); // Capture old parent if re-parented
}
}
}
}
}
}
if (accountIds.isEmpty()) {
return;
}
// Map out the number of pre-existing primary contacts for each tracked Account
Map<Id, Integer> accountPrimaryCountMap = new Map<Id, Integer>();
for (Contact existingCon : [SELECT Id, AccountId FROM Contact
WHERE AccountId IN :accountIds
AND Primary_Contact__c = true]) {
if (accountPrimaryCountMap.containsKey(existingCon.AccountId)) {
accountPrimaryCountMap.put(existingCon.AccountId, accountPrimaryCountMap.get(existingCon.AccountId) + 1);
} else {
accountPrimaryCountMap.put(existingCon.AccountId, 1);
}
}
// Validate records against criteria and add DML-blocking form errors
for (Contact con : newContacts) {
if (con.AccountId != null && con.Primary_Contact__c == true) {
Integer existingCount = accountPrimaryCountMap.containsKey(con.AccountId) ? accountPrimaryCountMap.get(con.AccountId) : 0;
if (oldContactMap == null && existingCount > 0) {
// Fail if inserting a new primary contact where one exists
con.addError('This account cannot have more than one primary contact.');
} else if (oldContactMap != null) {
Contact oldCon = oldContactMap.get(con.Id);
// Case A: Contact was already primary and re-parented to an account that has one
// Case B: Contact changed from regular to primary on an account that already has one
if ((oldCon.AccountId != con.AccountId && existingCount > 0) ||
(oldCon.AccountId == con.AccountId && oldCon.Primary_Contact__c == false && existingCount > 0)) {
con.addError('This account cannot have more than one primary contact.');
}
}
}
}
}
}
Use code with caution.
3. Apex Trigger
java
trigger ContactTrigger on Contact (before insert, before update) {
// Lock validation executions safely inside 'before' contexts to capture errors prior to commitments
if (Trigger.isBefore) {
if (Trigger.isInsert) {
ContactTriggerHandler.preventDuplicatePrimaryContacts(Trigger.new, null);
} else if (Trigger.isUpdate) {
ContactTriggerHandler.preventDuplicatePrimaryContacts(Trigger.new, Trigger.oldMap);
}
}
}
Comments
Post a Comment