Skip to content

Instantly share code, notes, and snippets.

@joshbirk
Created August 27, 2015 20:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshbirk/2b3f5d6611c11175269c to your computer and use it in GitHub Desktop.
Save joshbirk/2b3f5d6611c11175269c to your computer and use it in GitHub Desktop.
<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>

Step 1: Create a Trigger that Sends Confirmation Emails

In this step, you create a trigger that sends confirmation emails to speakers when they are assigned to a session.

  1. In the Developer Console, click File > New > Apex Trigger

  2. Specify SendConfirmationEmail as the trigger name, Session_Speaker__c as the sObject, and click Submit.

  3. 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&lt;Id&gt; sessionSpeakerIds = new List&lt;Id&gt;();    
    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&lt;Session_Speaker__c&gt; 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.

  4. Save the file. The trigger takes effect as soon as you save it.

  5. 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.

Step 2: Create a Trigger that Rejects Double Bookings

  1. In the Developer Console, click File > New > Apex Trigger.

  2. Specify RejectDoubleBooking as the trigger name, Session_Speaker__c as the sObject, and click Submit.

  3. Implement the trigger as follows:

    trigger RejectDoubleBooking on Session_Speaker__c (before insert, before update) {
    
    //collect ID's to reduce data calls 
    List&lt;Id&gt; speakerIds = new List&lt;Id&gt;();    
    Map&lt;Id,DateTime&gt; requested_bookings = new Map&lt;Id,DateTime&gt;();
    
    //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&lt;Session__c&gt; 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&lt;Session_Speaker__c&gt; 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 &amp;&amp;
               related_speaker.Session__r.Session_Date__c == booking_time) {
                   requested_session_speaker.addError(&#39;The speaker is already booked at that time&#39;);
               }
        }
    }
    

    }

  4. Save the file.

  5. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment