SF Learners Hub · Blog · About · Contact

Apex Trigger Interview Scenarios – Part 2

By Aman Garg · Published · Interview Questions

Apex Trigger Interview Scenarios – Part 2

Here are a few common Salesforce Apex Trigger Interview Scenarios along with their answers:

1. Create a trigger to change the account owner at the stage of close won.

trigger UpdateAccount on Opportunity (After Update){
	if(trigger.isAfter && trigger.isUpdate){

		List<Opportunity> oppsToUpdate = new List<Opportunity>();

		for (Opportunity opp : Trigger.new) {
			if(opp.stageName == 'Closed Won' || Trigger.oldMap.get(opp.Id).StageName != 'Close Won'){
				opp.Account.OwnerId = 'new_owner_id';
				oppsToUpdate.add(opp);
			}
		}
		if (!oppsToUpdate.isEmpty()) {
        update oppsToUpdate;
    	}	
	}
}

2. Create a trigger to update the amount field on the account object based on the contact amount.

trigger UpdateAccountAmountBasedOnContacts on Contact (after insert, after update, after delete) {
    Set<Id> accountIdsToUpdate = new Set<Id>();
    
    if (Trigger.isInsert || Trigger.isUpdate) {
        for (Contact contact : Trigger.new) {
            accountIdsToUpdate.add(contact.AccountId);
        }
    }
    
    if (Trigger.isDelete) {
        for (Contact contact : Trigger.old) {
            accountIdsToUpdate.add(contact.AccountId);
        }
    }
    
    List<Account> accountsToUpdate = new List<Account>();
    
    for (Id accountId : accountIdsToUpdate) {
        // Calculate the sum of Amount from related Contacts
        List<Contact> relatedContacts = [SELECT Amount__c FROM Contact WHERE AccountId = :accountId];
        Decimal totalAmount = 0;
        for (Contact c : relatedContacts) {
            if (c.Amount__c != null) {
                totalAmount += c.Amount__c;
            }
        }
        
        // Update the Amount field on the Account
        Account acc = new Account(Id = accountId, Amount__c = totalAmount);
        accountsToUpdate.add(acc);
    }
    
    // Perform the updates
    if (!accountsToUpdate.isEmpty()) {
        update accountsToUpdate;
    }
}

3. Create a trigger on the account to update the no of contact which is associated with the particular contact.

trigger UpdateContactCount on Contact (after insert, after update, after delete) {
    Set<Id> accountIds = new Set<Id>();

    if (Trigger.isInsert || Trigger.isUpdate) {
        for (Contact contact : Trigger.new) {
            accountIds.add(contact.AccountId);
        }
    }
    if (Trigger.isDelete) {
        for (Contact contact : Trigger.old) {
            accountIds.add(contact.AccountId);
        }
    }

    List<Account> accountsToUpdate = new List<Account>();

    for (Id accountId : accountIds) {
        // Query the number of Contacts associated with each Account
        Integer contactCount = [SELECT Count() FROM Contact WHERE AccountId = :accountId];
        
        // Retrieve the Account and update the Contact_Count__c custom field
        Account acc = new Account(Id = accountId, Contact_Count__c = contactCount);
        accountsToUpdate.add(acc);
    }

    if (!accountsToUpdate.isEmpty()) {
        update accountsToUpdate;
    }
}

4. Create a trigger on the account object to show an error message if the account has more than 2 contacts.

trigger UpdateContactCount on Contact (after insert, after update, after delete) {
    Set<Id> accountIds = new Set<Id>();

    if (Trigger.isInsert || Trigger.isUpdate) {
        for (Contact contact : Trigger.new) {
            accountIds.add(contact.AccountId);
        }
    }
    if (Trigger.isDelete) {
        for (Contact contact : Trigger.old) {
            accountIds.add(contact.AccountId);
        }
    }

    List<Account> accountsToUpdate = new List<Account>();

    for (Id accountId : accountIds) {
        Integer contactCount = [SELECT Count() FROM Contact WHERE AccountId = :accountId];
        Account acc = new Account(Id = accountId, NumberOfContacts__c = contactCount);
        accountsToUpdate.add(acc);
    }

    if (!accountsToUpdate.isEmpty()) {
        update accountsToUpdate;
    }
}

5. If any workOrderItem is associated with WorkOrder then update the primary checkbox is true.

trigger UpdatePrimaryOnWorkOrder on WorkOrderItem (after insert, after update, after delete, after undelete) {
    Set<Id> workOrderIds = new Set<Id>();

    if (Trigger.isInsert || Trigger.isUpdate || Trigger.isDelete || Trigger.isUndelete) {
        for (WorkOrderItem workOrderItem : Trigger.new) {
            workOrderIds.add(workOrderItem.WorkOrderId);
        }
    }

    List<WorkOrder> workOrdersToUpdate = new List<WorkOrder>();

    for (Id workOrderId : workOrderIds) {
        // Query for related Work Order Items
        List<WorkOrderItem> relatedWorkOrderItems = [SELECT Id FROM WorkOrderItem WHERE WorkOrderId = :workOrderId];

        // Update the "Primary" checkbox on the Work Order
        WorkOrder workOrder = new WorkOrder(Id = workOrderId, Primary__c = !relatedWorkOrderItems.isEmpty());
        workOrdersToUpdate.add(workOrder);
    }

    if (!workOrdersToUpdate.isEmpty()) {
        update workOrdersToUpdate;
    }
}

6. write a trigger on the opportunity to show an error when the opportunity stage is closed won and someone trying to change the stage of opportunity

trigger PreventClosedWonChange on Opportunity (before update) {
    for (Opportunity opp : Trigger.new) {
        // Check if the stage is changing to "Closed Won"
        if (opp.StageName == 'Closed Won') {
            // Check if the previous stage was not "Closed Won"
            Opportunity oldOpp = Trigger.oldMap.get(opp.Id);
            if (oldOpp.StageName != 'Closed Won') {
                opp.addError('You cannot change the stage to "Closed Won."');
            }
        }
    }
}

7. Write a trigger to restrict the user from creating an opportunity at 2nd time if the opportunity already exists

trigger PreventDuplicateOpportunity on Opportunity (before insert) {
    Set<String> opportunityNames = new Set<String>();
    
    for (Opportunity opp : Trigger.new) {
        opportunityNames.add(opp.Name);
    }
    
    // Query for existing opportunities with the same name
    List<Opportunity> existingOpportunities = [SELECT Name FROM Opportunity WHERE Name IN :opportunityNames];
    
    for (Opportunity opp : Trigger.new) {
        for (Opportunity existingOpp : existingOpportunities) {
            if (opp.Name == existingOpp.Name) {
                opp.addError('An opportunity with the same name already exists.');
            }
        }
    }
}

8. Write a trigger to update the address on the contact whenever update the address on account

trigger UpdateContactAddress on Account (after update) {
    List<Contact> contactsToUpdate = new List<Contact>();

    // Loop through the updated accounts
    for (Account updatedAccount : Trigger.new) {
        // Check if the Account's address fields have changed
        if (Trigger.oldMap.get(updatedAccount.Id).BillingStreet != updatedAccount.BillingStreet ||
            Trigger.oldMap.get(updatedAccount.Id).BillingCity != updatedAccount.BillingCity ||
            Trigger.oldMap.get(updatedAccount.Id).BillingState != updatedAccount.BillingState ||
            Trigger.oldMap.get(updatedAccount.Id).BillingPostalCode != updatedAccount.BillingPostalCode ||
            Trigger.oldMap.get(updatedAccount.Id).BillingCountry != updatedAccount.BillingCountry) {

            // Query for related contacts
            List<Contact> relatedContacts = [SELECT Id, MailingStreet, MailingCity, MailingState, MailingPostalCode, MailingCountry
                                            FROM Contact
                                            WHERE AccountId = :updatedAccount.Id];

            // Update the address on related contacts
            for (Contact contact : relatedContacts) {
                contact.MailingStreet = updatedAccount.BillingStreet;
                contact.MailingCity = updatedAccount.BillingCity;
                contact.MailingState = updatedAccount.BillingState;
                contact.MailingPostalCode = updatedAccount.BillingPostalCode;
                contact.MailingCountry = updatedAccount.BillingCountry;
                contactsToUpdate.add(contact);
            }
        }
    }

    // Update the related contacts
    if (!contactsToUpdate.isEmpty()) {
        update contactsToUpdate;
    }
}

9. Write an apex method that takes a list of IDs of contacts and returns all the related accounts.

public class ContactAccountUtils {

    // Method to retrieve related accounts for a list of contact IDs
    public static List<Account> getRelatedAccounts(List<Id> contactIds) {
        List<Account> relatedAccounts = new List<Account>();

        // Query to retrieve related accounts for the given contact IDs
        List<Contact> relatedContacts = [SELECT Id, AccountId FROM Contact WHERE Id IN :contactIds];
        Set<Id> accountIds = new Set<Id>();

        // Extracting Account IDs from related contacts
        for (Contact relatedContact : relatedContacts) {
            accountIds.add(relatedContact.AccountId);
        }

        // Query to retrieve related accounts for the extracted Account IDs
        if (!accountIds.isEmpty()) {
            relatedAccounts = [SELECT Id, Name FROM Account WHERE Id IN :accountIds];
        }

        return relatedAccounts;
    }
}
trigger ContactTrigger on Contact (after insert, after update) {
    List<Id> contactIds = new List<Id>();

    for (Contact contact : Trigger.new) {
        contactIds.add(contact.Id);
    }

    List<Account> relatedAccounts = ContactAccountUtils.getRelatedAccounts(contactIds);

}

Related articles