Skip to main content

Command Palette

Search for a command to run...

Apex Trigger Practice Problem

Updated
14 min readView as Markdown

Problem 1: Prevent Lead Conversion If No Email

Scenario: Create a trigger on the Lead object that prevents conversion if the Email field is blank.

Requirements:

  • Trigger should run before update on Lead.

  • If the Lead has no email address and a user tries to convert it, display an error message: "Lead must have an email address before conversion."


Problem 2: Automatically Create a Task on Account Creation

Scenario: Create a trigger on the Account object that automatically creates a Task when a new Account record is created. The task should have the following properties:

  • Subject: "Welcome Call"

  • Due Date: 3 days from today

  • Priority: "High"

  • Owner: Same as the Account Owner

Requirements:

  • Trigger should run after insert.

  • Ensure the task is created only once per Account.

  • Use the Account's owner as the task owner.


Problem 3: Update Opportunity Stage Based on Close Date

Scenario: Create a trigger on the Opportunity object that automatically sets the StageName to "Closed Won" when the CloseDate is set to today’s date.

Requirements:

  • Trigger should run before update.

  • The trigger should update the StageName only if the CloseDate is today and the StageName is not already "Closed Won."

// update opportunity stage based on close date
    public void updateOpportunityStage(List<Opportunity> opportunityList, Map<Id, Opportunity> oldOpportunityMap) {
        for (Opportunity opportunity : opportunityList) {
            Date oldOpportunityDate = oldOpportunityMap.get(opportunity.Id).CloseDate;
            String oldOpportunityStageName = oldOpportunityMap.get(opportunity.Id).StageName;
            if (opportunity.CloseDate != oldOpportunityDate && oldOpportunityStageName != 'Closed Won' && opportunity.CloseDate == System.today()) {
                opportunity.StageName = 'Closed Won';
            }
        }
    }

Problem 4: Enforce Required Contact Field for Account Type

Scenario: Create a trigger on the Account object that ensures if the Account type is "Customer," the related Contact record must have a Phone number provided.

Requirements:

  • Trigger should run before insert and before update on Account.

  • If the Account type is "Customer," ensure the related Contact has a Phone number. If not, prevent saving the Account and display an error: "Customer accounts must have a phone number on the associated contact."


Problem 5: Roll-Up Summary of Opportunities to Account

Scenario: Create an Apex trigger on the Opportunity object to maintain a custom field on the related Account object. The custom field, Total_Opportunities__c, will hold the total number of Opportunities related to the Account that are in the "Closed Won" stage.

Requirements:

  • Trigger should run after insert, after update, and after delete.

  • Perform bulk processing and use a map to efficiently update Account records.

  • Update the Total_Opportunities__c on the Account when an Opportunity is inserted, updated, or deleted.

Solution:

  • OpportunityTrigger
trigger OpportunityTrigger on Opportunity (after update, before update, after insert, after delete) {
    OpportunityTriggerHandler opportunityTriggerHandler = new OpportunityTriggerHandler();

    if (Trigger.isUpdate) {        
        if (Trigger.isAfter) {
            opportunityTriggerHandler.updateTotalNumberOfOpportunities(Trigger.New);
        }
    }

     if (Trigger.isInsert) {
        if (Trigger.isAfter) {
            opportunityTriggerHandler.updateTotalNumberOfOpportunities(Trigger.New);
        }
    }


    if (Trigger.isDelete) {
        if (Trigger.isAfter) {
            opportunityTriggerHandler.updateTotalNumberOfOpportunities(Trigger.New);
        }
    }
}
  • OpportunityTriggerHandler
public class OpportunityTriggerHandler {
    public void updateTotalNumberOfOpportunities(List<Opportunity> opportunityList) {
        Set<Id> accountIds = new Set<Id>();
        for (Opportunity opportunity : opportunityList) {
            accountIds.add(opportunity.AccountId);
        }

        List<Account> accountList = new List<Account>();
        for (Account account : [SELECT Id, (SELECT Id FROM Opportunities WHERE StageName = 'Closed Won') FROM Account WHERE Id IN :accountIds]) {
            Account currentAccount = new Account();
            currentAccount.Id = account.Id;
            currentAccount.Total_Opportunities__c = account.Opportunities.size();

            accountList.add(currentAccount);
        }

        try {
            update accountList;
        } catch (Exception e) {
            System.debug(e.getMessage());
        }
    }
}

Problem 6: Prevent Deletion of Accounts with Active Opportunities

Scenario: Create a trigger on the Account object that prevents the deletion of an Account if there are any related Opportunities with a StageName of "Perception Analysis" or "Proposal/Price Quote."

Requirements:

  • Trigger should run before delete on Account.

  • If the Account has any related Opportunities in "Negotiation" or "Proposal" stage, throw an error: "Cannot delete an Account with active Opportunities."

Solution:

  • AccountTrigger
if(Trigger.isDelete) {
        if (Trigger.isBefore) {
            accountTriggerHandler.preventDeletionOfAccountWithActiveOpportunities(Trigger.Old);
        }
    }
  • AccountTriggerHandler
public void preventDeletionOfAccountWithActiveOpportunities(List<Account> accountList) {
        System.debug('Prevent delete function called');

        Set<Id> accountIds = new Set<Id>();
        for (Account account : accountList) {
            accountIds.add(account.Id);
        }

        System.debug('Account Ids : ' + accountIds);

        List<String> stages = new List<String>{'Perception Analysis', 'Proposal/Price Quote'};
        Set<Id> accountIdWithRelatedOpportunity = new Set<Id>();
        for (Opportunity opportunity : [SELECT AccountId FROM Opportunity WHERE StageName IN :stages AND AccountId IN :accountIds]) {
            accountIdWithRelatedOpportunity.add(opportunity.AccountId);
        }

        System.debug('Account Ids with related opportunity : ' + accountIdWithRelatedOpportunity);

        for (Account account : accountList) {
            if (accountIdWithRelatedOpportunity.contains(account.Id)) {
                account.addError('Account cannot be deleted as it has related opportunity with Perception Analysis or Proposal/Price Quote ');
                System.debug('Inside loop');
            }
        }
    }

Problem 7: Update Contact’s Email on Opportunity Stage Change

Scenario: Create a trigger on the Opportunity object. When the StageName is changed to "Closed Won," update the Email field of the related Contact to a predefined value (e.g., "won@opportunity.com").

Requirements:

  • Trigger should run after update on Opportunity.

  • The trigger should check if the StageName is updated to "Closed Won" and update the Email field of the related Contact.

  • Ensure the email update happens only if the Contact's Email field is not already set to the predefined value.

Solution:

  • OpportunityTriggerHandler
public void updateContactEmailField(List<Opportunity> opportunityList, Map<Id, Opportunity> oldOpportunityMap) {
        Set<Id> contactIds = new Set<Id>();


        for (Opportunity opportunity : opportunityList) {
            if (opportunity.StageName != oldOpportunityMap.get(opportunity.Id).StageName && opportunity.StageName == 'Closed Won') {
                contactIds.add(opportunity.ContactId);
            }
        }
        System.debug('Contact Ids : ' + contactIds);

        List<Contact> contactList = new List<Contact>();
        for (Contact contact : [SELECT Id, Email FROM Contact WHERE Id IN :contactIds]) {
            contact.email = 'won@opportunity.com';
            contactList.add(contact);
        }
        System.debug('Contacts : ' + contactList);

        try {
            if (!contactList.isEmpty()) {
                update contactList;
                System.debug('Contacts updated');
            }
        } catch (Exception e) {
            System.debug('Exception : ' + e.getMessage());
        }
    }
  • OpportunityTrigger
trigger OpportunityTrigger on Opportunity (after update, before update, after insert, after delete) {
    OpportunityTriggerHandler opportunityTriggerHandler = new OpportunityTriggerHandler();

    if (Trigger.isUpdate) {
        if (Trigger.isAfter) {
            // Update Contact’s Email on Opportunity Stage Change
            opportunityTriggerHandler.updateContactEmailField(Trigger.New, Trigger.OldMap); 
        }
    }
}

Problem 8: Prevent Account Creation with Duplicate Account Name

Scenario: Create a trigger on the Account object that prevents the creation of a new Account if an Account with the same Name already exists within the same Industry.

Requirements:

  • Trigger should run before insert on Account.

  • If a duplicate Account name exists within the same Industry, prevent the Account from being created and display an error: "An Account with the same name already exists in this Industry."

Solution:

  • AccountTriggerHandler
// trigger runs before account is inserted
public void preventDuplicateAccountWithinSameIndustry(List<Account> accountList) {
        // store all account name
        List<String> accountNames = new List<String>();
        for (Account account : accountList) {
            accountNames.add(account.Name);
        }

        // get all matching account and store inm map
        Map<String, Account> accountsFromObject = new Map<String, Account>();
        for (Account account : [SELECT Id, Name, Industry FROM Account WHERE Name IN :accountNames]) {
            accountsFromObject.put(account.Name, account);
        }

        // check if account name already exist's within the same industry
        for (Account account : accountList) {
            if (accountsFromObject.containsKey(account.Name) && accountsFromObject.get(account.Name).Industry == account.Industry) {
                account.addError('Account Name : ' + account.Name + ' exist with ' + account.Industry);
            }
        }
    }

Problem 9: Calculate Total Opportunity Value for Account

Scenario: Create a trigger on the Opportunity object that updates a custom field Total_Opportunity_Value__c on the related Account with the sum of the Amount field of all related opportunities that are "Closed Won."

Requirements:

  • Trigger should run after insert, after update, and after delete.

  • Perform bulk processing to handle updates on multiple records efficiently.

  • Ensure the sum is recalculated when an opportunity’s Amount changes, or an opportunity is deleted.

// calculate total opportunity value for account after update
    public void calculateTotalOpportunityValueAfterUpdate(List<Opportunity> opportunityList, Map<Id, Opportunity> oldOpportunityMap) {
        Set<Id> accountIds = new Set<Id>();
        for (Opportunity opportunity : opportunityList) {
            Decimal oldOpportunityAmount = oldOpportunityMap.get(opportunity.Id).Amount;
            String oldStageName = oldOpportunityMap.get(opportunity.Id).StageName;

            if (opportunity.Amount != oldOpportunityAmount || ((opportunity.StageName != oldStageName) && opportunity.StageName == 'Closed Won')) {
                accountIds.add(opportunity.AccountId);
            }
        }

        List<Account> accountList = new List<Account>();
        for (Account account : [SELECT Id, (SELECT Amount FROM Opportunities WHERE StageName = 'Closed Won') FROM Account WHERE Id IN :accountIds]) {

            // calculate total amount
            Decimal totalAmount = 0;
            for (Opportunity opp : account.Opportunities) {
                totalAmount += opp.Amount;
            }

            // update total opportunity value field
            account.Total_Opportunity_Value__c = totalAmount;
            accountList.add(account);
        }

        System.debug('Account list : ' + accountList);

        if (!accountList.isEmpty()) {
            update accountList;
            System.debug('Account updated');
        }
    }

Problem 10: Calculate Total Opportunity Value for Account After Insert

// calculate total opportunity value for account after insert and update
    public void calculateTotalOpportunityValue(List<Opportunity> opportunityList) {
        Set<Id> accountIds = new Set<Id>();
        for (Opportunity opportunity : opportunityList) {
            accountIds.add(opportunity.AccountId);
        }

        List<Account> accountList = new List<Account>();
        for (Account account : [SELECT Id, (SELECT Amount FROM Opportunities WHERE StageName = 'Closed Won') FROM Account WHERE Id IN :accountIds]) {

            // calculate total amount
            Decimal totalAmount = 0;
            for (Opportunity opp : account.Opportunities) {
                totalAmount += opp.Amount;
            }

            // update total opportunity value field
            account.Total_Opportunity_Value__c = totalAmount;
            accountList.add(account);
        }

        System.debug('Account list : ' + accountList);

        if (!accountList.isEmpty()) {
            update accountList;
            System.debug('Account updated');
        }
    }

Problem 11: Calculate Total Opportunity Value for Account After Delete

// calculate total opportunity value for account after insert and update
    public void calculateTotalOpportunityValue(List<Opportunity> opportunityList) {
        Set<Id> accountIds = new Set<Id>();
        for (Opportunity opportunity : opportunityList) {
            accountIds.add(opportunity.AccountId);
        }

        List<Account> accountList = new List<Account>();
        for (Account account : [SELECT Id, (SELECT Amount FROM Opportunities WHERE StageName = 'Closed Won') FROM Account WHERE Id IN :accountIds]) {

            // calculate total amount
            Decimal totalAmount = 0;
            for (Opportunity opp : account.Opportunities) {
                totalAmount += opp.Amount;
            }

            // update total opportunity value field
            account.Total_Opportunity_Value__c = totalAmount;
            accountList.add(account);
        }

        System.debug('Account list : ' + accountList);

        if (!accountList.isEmpty()) {
            update accountList;
            System.debug('Account updated');
        }
    }

Problem 12: Auto-Assign Tasks Based on Opportunity Stage

Scenario: Create a trigger on the Opportunity object that automatically assigns a task to the Opportunity owner based on the StageName. The task should have the following:

  • Subject: "Follow-up on Opportunity"

  • Due Date: 7 days from the CloseDate

  • Priority: "Medium"

Requirements:

  • Trigger should run after update on Opportunity.

  • Create the task only when the StageName is updated to specific stages (e.g., "Negotiation," "Proposal").

  • Ensure the task is assigned to the Opportunity Owner.

OpportunityTrigger

trigger OpportunityTrigger on Opportunity (after update, before update, after insert, after delete) {

    if (Trigger.isUpdate) {
        if (Trigger.isAfter) {
            // create task for opportunity owner when StageName is updated to 'Closed Won'
            opportunityTriggerHandler.autoAssignTaskBasedOnOpportunityStage(Trigger.New, Trigger.OldMap);
        }
    }
}

OpportunityTriggerHandler

public void autoAssignTaskBasedOnOpportunityStage(List<Opportunity> opportunityList, Map<Id, Opportunity> opportunityOldMap) {
        List<Task> taskList = new List<Task>();

        for (Opportunity opportunity : opportunityList) {
            String oldStageName = opportunityOldMap.get(opportunity.Id).StageName;
            if (opportunity.StageName != oldStageName && (opportunity.StageName == 'Closed Won')) {
                Task task = new Task();
                task.OwnerId = opportunity.OwnerId;
                task.WhatId = opportunity.Id;
                task.ActivityDate = System.today() + 7;
                task.Priority = 'Medium';
                task.subject = 'Follow-up on Opportunity';

                taskList.add(task);
            }
        }

        System.debug('Task list : ' + taskList);

        if (!taskList.isEmpty()) {
            insert taskList;
            System.debug('Task created');
        }
    }

Problem 13: Prevent duplicate Account name

// This handler function run's : BEFORE INSERT

public void preventDuplicateAccountandIndustry(List<Account> accountList) {
        // store all account name
        List<String> accountNames = new List<String>();
        for (Account account : accountList) {
            accountNames.add(account.Name);
        }

        // get all matching account names
        List<String> accountNamesFromObject = new List<String>();
        for (Account account : [SELECT Id, Name FROM Account WHERE Name IN :accountNames]) {
            accountNamesFromObject.add(account.Name);
        }

        // check if account name already exist's
        for (Account account : accountList) {
            if (accountNamesFromObject.contains(account.Name)) {
                account.addError('Account with ' + account.Name + ' already exists');
            }
        }
   }

Problem 14 : Prevent Duplicate Account name with same Industry

public void preventDuplicateAccountWithinSameIndustry(List<Account> accountList) {
        // store all account name
        List<String> accountNames = new List<String>();
        for (Account account : accountList) {
            accountNames.add(account.Name);
        }

        System.debug('Account Names : ' + accountNames);

        Map<String, Account> accountsFromObject = new Map<String, Account>();
        for (Account account : [SELECT Id, Name, Industry FROM Account WHERE Name IN :accountNames]) {
            accountsFromObject.put(account.Name, account);
            System.debug('Added to map');
        }

        System.debug('Accounts From Object ' + accountsFromObject);

        for (Account account : accountList) {
            if (accountsFromObject.containsKey(account.Name) && accountsFromObject.get(account.Name).Industry == account.Industry) {
                account.addError('Account Name : ' + account.Name + ' exist with ' + account.Industry);
            }
        }
    }
  • Update related contacts of the account whose phone field is updated
public void updateRelatedContacts(List<Account> accountList, Map<Id, Account> accountOldMap) {
        Map<Id, String> accountWithPhoneList = new Map<Id, String>();

        for (Account account : accountList) {
            String oldAccountPhone = accountOldMap.get(account.Id).Phone;
            if (account.Phone != oldAccountPhone) {
                accountWithPhoneList.put(account.Id, account.Phone);
            }
        }

        System.debug('Accounts with phone list '+ accountWithPhoneList);

        List<Contact> contactList = new List<Contact>();
        for (Contact contact : [SELECT Id, AccountId, Phone FROM Contact WHERE AccountId IN :accountWithPhoneList.keySet()]) {
            contact.Phone = accountWithPhoneList.get(contact.AccountId);
            contactList.add(contact);
        }

        System.debug('Contacts ' + contactList);

        if (!contactList.isEmpty()) {
            update contactList;
            System.debug('Contact List updated');
        }
    }

Problem 16: Check Primary Contact on Insert

public void checkPrimaryContact(List<Contact> contactList) {
        Map<Id, Contact> mp = new Map<Id, Contact>();

        for (Contact contact : contactList) {
            mp.put(contact.AccountId, contact);
        }

        for (Account account : [SELECT Id, (SELECT Id , AccountId, Primary_Contact__c FROM Contacts) FROM Account WHERE Id IN :mp.keySet()]) {
            System.debug('Current Account ' + account);

            // check if primary contact exist
            for (Contact contact : account.Contacts) {
                if (contact.Primary_Contact__c && mp.get(contact.AccountId).Primary_Contact__c == true) {
                    mp.get(contact.AccountId).addError('Primary contact Exist');
                }
            }
        }
    }

Problem 17: Check Primary contact on update

public void checkPrimaryContactAfterUpdate(Map<Id, Contact> contactMap, Map<Id, Contact> oldContactMap) {
        Map<Id, Contact> contactsWithAccountId = new Map<Id, Contact>();

        for (Contact contact : contactMap.values()) {
            if (contact.Primary_Contact__c != oldContactMap.get(contact.Id).Primary_Contact__c) {
                contactsWithAccountId.put(contact.AccountId, contact);
            }
        }

        for (Account account : [SELECT Id, (SELECT Id , AccountId, Primary_Contact__c FROM Contacts) FROM Account WHERE Id IN :contactsWithAccountId.keySet()]) {
            System.debug('Current Account ' + account);

            // check if primary contact exist
            for (Contact contact : account.Contacts) {
                if (contact.Primary_Contact__c && contactsWithAccountId.get(contact.AccountId).Primary_Contact__c == true) {
                    contactsWithAccountId.get(contact.AccountId).addError('Primary contact Exist');
                }
            }
        }
    }

Problem 18: Create Contact according to total contact field

// after insert trigger
public void createContactsAccordingToTotalContactField(List<Account> accountList) {
        System.debug('createContactsAccordingToTotalContactField');
        List<Contact> contactList = new List<Contact>();
        for (Account account : accountList) {
            Integer totalContacts = (Integer) account.Total_Number_of_Contacts__c;

            // create Contacts
            for (Integer i = 0; i < totalContacts; i++) {
                Contact contact = new Contact(LastName=account.Name);
                contact.AccountId = account.Id;
                contactList.add(contact);
            }
        }

        System.debug('Contact list ' + contactList);

        if (!contactList.isEmpty()) {
            insert contactList;
            System.debug('Contact inserted');
        }
    }
// before insert trigger on contact
public void createAccountBeforeCreatingContact(List<Contact> contactList) {

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

        for (Contact contact : contactList) {
            Account account = new Account(Name=contact.LastName);
            accountList.add(account);
        }

        if (!accountList.isEmpty()) {
            insert accountList;
            System.debug('Account created');

            for (Integer i = 0; i < contactList.size(); i++) {
                contactList[i].AccountId = accountList[i].Id;
            }
        }
    }

Problem 20: Prevent user from deactivation if there are active cases for that user

public void preventDeactivationOfUserForActiveCases(Map<Id, User> userMap, Map<Id, User> oldUserMap) {

        Set<Id> userIds = new Set<Id>();
        for (User user : userMap.values()) {
            if (user.IsActive != oldUserMap.get(user.Id).IsActive && user.IsActive == false) {
                userIds.add(user.Id);
            }
        }

        System.debug('Users' + userIds);

        for (Case currentCase : [SELECT Id, OwnerId FROM Case WHERE Status != 'Closed' AND OwnerId IN :userIds]) {
            if (currentCase != null) {
                userMap.get(currentCase.OwnerId).addError('Cannot deactive user cases are active on it');
                System.debug('Cannot deactivate user');
            }
        }
    }
public void updateRelatedContactsOptimized(Map<Id, Account> newAccountMap, Map<Id, Account> oldAccountMap) {
        Set<Id> accountIds = new Set<Id>();
        for (Account account : newAccountMap.values()) {
            if (account.Phone != oldAccountMap.get(account.Id).Phone) {
                accountIds.add(account.Id);
            }
        }

        List<Contact> contactList = new List<Contact>();
        for (Contact contact : [SELECT Id, AccountId, Phone FROM Contact WHERE AccountId IN :accountIds]) {
            contact.Phone = newAccountMap.get(contact.AccountId).Phone;
            contactList.add(contact);
        }

        if (!contactList.isEmpty()) {
            update contactList;
            System.debug('Contacts updated');
        }
    }

Problem 22 : No conflict should be there while inserting timetable (Project Trigger)

public void handleTimetableBeforeInsert(List<Timetable__c> timetableList) {
        Map<Id, Timetable__c> timetableWithCourseId = new Map<Id, Timetable__c>();
        Map<Id, Timetable__c> timetableWithFactultyId = new Map<Id, Timetable__c>();
        List<Date> scheduledDate = new List<Date>();
        List<String> timeSlotList = new List<String>();

        for (Timetable__c timetable : timetableList) {
            timetableWithCourseId.put(timetable.Course__c, timetable);
            timetableWithFactultyId.put(timetable.Faculties__c, timetable);
            scheduledDate.add(timetable.Scheduled_Date__c);
            timeSlotList.add(timetable.Subject_Time_Slot__c);
        }

        // check if faculty is already assined to this timetable
        for (Timetable__c timetable : [SELECT Id, Course__c FROM Timetable__c WHERE Course__c IN :timetableWithCourseId.keySet()
                                           AND Scheduled_Date__c IN :scheduledDate 
                                        AND Subject_Time_Slot__c IN :timeSlotList]) 
        {
            timetableWithCourseId.get(timetable.Course__c).addError('Timetable for this course is already set');
        }

        // check if faculty is been allocated to other course with same time
        for (Timetable__c timetable : [SELECT Id, Faculties__c FROM Timetable__c WHERE Faculties__c IN :timetableWithFactultyId.keySet()
                                           AND Scheduled_Date__c IN :scheduledDate 
                                        AND Subject_Time_Slot__c IN :timeSlotList]) 
        {
            timetableWithFactultyId.get(timetable.Faculties__c).addError('Timetable for this faculty is already set');
        }        
    }

Problem 23 : Check if valid subject belongs to selected course while adding timetable (Project Trigger)

public void handleSubjectsForCourse(List<Timetable__c> timetableList) {
        List<Id> timetableWithCourseId = new List<Id>();
        List<Id> timetableWithFacultyId = new List<Id>();

        for (Timetable__c timetable : timetableList) {
            timetableWithCourseId.add(timetable.Course__c);
            timetableWithFacultyId.add(timetable.Faculties__c);
        }

        Map<Id, String> subjectWithFacultyId = new Map<Id, String>();
        for (Faculties__c faculty : [SELECT Id, Subject__c FROM Faculties__c WHERE Id IN :timetableWithFacultyId]) {
            subjectWithFacultyId.put(faculty.Id, faculty.Subject__c);
        }

        Map<Id, Set<Id>> subjectsWithCourseId = new Map<Id, Set<Id>>();
        for (Subject_Course__c subject : [SELECT Course__c, Subject__c FROM Subject_Course__c WHERE Course__c IN :timetableWithCourseId]) {
            if (subjectsWithCourseId.containsKey(subject.Course__c) && subjectsWithCourseId.get(subject.Course__c) != null) {
                subjectsWithCourseId.get(subject.Course__c).add(subject.Subject__c);
            } 
            else {
                subjectsWithCourseId.put(subject.Course__c, new Set<Id>{subject.Subject__c});
            }
        }

        for (Timetable__c timetable : timetableList) {
            String subjectId = subjectWithFacultyId.get(timetable.Faculties__c);
            if (!subjectsWithCourseId.get(timetable.Course__c).contains(subjectId)) {
                timetable.addError('Subject is not listed in course');
            }
        }
    }

Problem 24 : Handle student enrollment in course, throw error if student is already enrolled in any course (Project Trigger)

public void handleEnrollment(List<Enrollment__c> enrollmentList) {
        Map<Id, Enrollment__c> enrollmentsByStudentId = new Map<Id, Enrollment__c>();
        Map<Id, Enrollment__c> enrollmentsByCourseId = new Map<Id, Enrollment__c>();

        for (Enrollment__c enrollment : enrollmentList) {
            enrollmentsByStudentId.put(enrollment.Student__c, enrollment);
            enrollmentsByCourseId.put(enrollment.Course__c, enrollment);
        }

        // check if course is finished already
        for (Course__c course : [SELECT Id, End_Date__c FROM Course__c WHERE Id IN: enrollmentsByCourseId.keySet()]) {
            if (enrollmentsByCourseId.containsKey(course.Id) && course.End_Date__c < System.today()) {
                enrollmentsByCourseId.get(course.Id).addError('Course has been completed');
            }
        }

        for (Enrollment__c enrollment : [SELECT Student__r.Id, Course__r.Id, Course__r.End_Date__c FROM Enrollment__c WHERE Student__c IN :enrollmentsByStudentId.keySet()]) {                    
            if (enrollmentsByStudentId.containsKey(enrollment.Student__r.Id)) {

                // check for same course
                if (enrollmentsByStudentId.get(enrollment.Student__r.Id).Course__c == enrollment.Course__r.Id) {
                    enrollmentsByStudentId.get(enrollment.Student__r.Id).addError('Student already enrolled in this course');
                }

                // check if student is already enrolled in other course and that course is not finished
                if (enrollmentsByStudentId.get(enrollment.Student__r.Id).Course__c != enrollment.Course__r.Id && enrollment.Course__r.End_Date__c >= System.today()) {
                    enrollmentsByStudentId.get(enrollment.Student__r.Id).addError('Student already enrolled in other course');     
                }
            }
        }
    }

More from this blog

Untitled Publication

35 posts