<title>Salesforce Developer Workshop</title>
<h2>Creating Apex Triggers</h2>
<hr/>
<h3>What You'll Do</h3>
<ul>
<li><p>Create an Apex trigger that sends confirmation emails to speakers when they are assigned to a session.</p></li>
<li><p>Create another trigger that rejects double bookings of speakers.</p></li>
</ul>
In this step, you create a trigger that sends confirmation emails to speakers when they are assigned to a session.
In the Developer Console, click File > New > Apex Trigger
Specify SendConfirmationEmail as the trigger name, Session_Speaker__c as the sObject, and click Submit.
Implement the trigger as follows:
trigger SendConfirmationEmail on Session_Speaker__c (after insert) {
//collect ID's in one list of a single SOQL query List<Id> sessionSpeakerIds = new List<Id>(); for(Session_Speaker__c newItem : trigger.new) { sessionSpeakerIds.add(newItem.Id); } // Retrieve session name and time + speaker name and email address related to ID's List<Session_Speaker__c> sessionSpeakers = [SELECT Session__r.Name, Session__r.Session_Date__c, Speaker__r.First_Name__c, Speaker__r.Last_Name__c, Speaker__r.Email__c FROM Session_Speaker__c WHERE Id IN :sessionSpeakerIds]; if(sessionSpeakers.size() > 0) { // Send confirmation email if we know the speaker's email address Session_Speaker__c sessionSpeaker = sessionSpeakers[0]; if (sessionSpeaker.Speaker__r.Email__c != null) { String address = sessionSpeaker.Speaker__r.Email__c; String subject = 'Speaker Confirmation'; String message = 'Dear ' + sessionSpeaker.Speaker__r.First_Name__c + ',\nYour session "' + sessionSpeaker.Session__r.Name + '" on ' + sessionSpeaker.Session__r.Session_Date__c + ' is confirmed.\n\n' + 'Thanks for speaking at the conference!'; EmailManager.sendMail(address, subject, message); } } }
In a real-life application, hardcoding the email message is not a recommended approach. Consider using email templates instead.
Save the file. The trigger takes effect as soon as you save it.
Test the trigger.
- Create a speaker that has your own email address.
- Assign that speaker to a session, and check your email: you should receive a speaker confirmation email.
Sending a confirmation email when a speaker is assigned to a session (in other words, when a Session_Speaker__c record is created) can be accomplished without writing code by defining a workflow rule. The programmatic approach used in this workshop allows you to satisfy additional requirements. For example, sending a confirmation email "on demand", independently of a record being created or updated.
In the Developer Console, click File > New > Apex Trigger.
Specify RejectDoubleBooking as the trigger name, Session_Speaker__c as the sObject, and click Submit.
Implement the trigger as follows:
trigger RejectDoubleBooking on Session_Speaker__c (before insert, before update) {
//collect ID's to reduce data calls List<Id> speakerIds = new List<Id>(); Map<Id,DateTime> requested_bookings = new Map<Id,DateTime>(); //get all speakers related to the trigger //set booking map with ids to fill later for(Session_Speaker__c newItem : trigger.new) { requested_bookings.put(newItem.Session__c,null); speakerIds.add(newItem.Speaker__c); } //fill out the start date/time for the related sessions List<Session__c> related_sessions = [SELECT ID, Session_Date__c from Session__c WHERE ID IN :requested_bookings.keySet()]; for(Session__c related_session : related_sessions) { requested_bookings.put(related_session.Id,related_session.Session_Date__c); } //get related speaker sessions to check against List<Session_Speaker__c> related_speakers = [SELECT ID, Speaker__c, Session__c, Session__r.Session_Date__c from Session_Speaker__c WHERE Speaker__c IN :speakerIds]; //check one list against the other for(Session_Speaker__c requested_session_speaker : trigger.new) { DateTime booking_time = requested_bookings.get(requested_session_speaker.Session__c); for(Session_Speaker__c related_speaker : related_speakers) { if(related_speaker.Speaker__c == requested_session_speaker.Speaker__c && related_speaker.Session__r.Session_Date__c == booking_time) { requested_session_speaker.addError('The speaker is already booked at that time'); } } }
}
Save the file.
Test the trigger:
- Assign a speaker to a session scheduled at a time the speaker is available and make sure it still works.
- Assign a speaker to a session scheduled at the same time as another session the speaker is already assigned to: you should see the error message.
RejectDoubleBooking is not sufficient to entirely prevent the double booking of speakers. For example, the user could change the date and time of a session in a way that creates a double booking for a speaker assigned to that session. You could create an additional trigger to take care of that situation.
Also note that it would be less code to simply loop through the Session Speaker objects and query for conflicts one by one. However, triggers can work off both single records and bulk load operations. Running a query for every record can quickly hit governor limits. This design, also known as bulkifing your code, allows the trigger to use the same number of queries despite number of records effected by the trigger.