Example: Automatic Live Call Scheduling
  • 12 Oct 2021
  • 5 Minutes to read
  • Dark
    Light
  • PDF

Example: Automatic Live Call Scheduling

  • Dark
    Light
  • PDF

Article Summary

A common use case is wanting to add live calls to scheduled events. In this example, we'll explore how to add Live Calls to the ServiceAppointment object. A live call will be created automatically whenever a ServiceAppointment is scheduled, and we'll keep the Live session scheduled start time in sync if the appointment is rescheduled.

The Setup

For this example, the instance we will be using is pre-configured with Field Service and the Lightning Scheduler. We will be working with the ServiceAppointment object.

  1. We will use the Process Builder to set up a process to keep our live calls in sync with our ServiceAppointments.
  2. First, we will create three Apex classes to work with our ServiceAppointmentbased Process.
    • HookCreateScheduledLiveSession - For scheduling a new live session.
    • HookRescheduleLiveSession - For re-scheduling an existing live session
    • HookCancelScheduledLiveSession - For cancelling a scheduled live session
  3. We will use a trigger on the ScreenMeet Live Session object to ensure our ServiceAppointment is associated with our live call.
  4. Then, we will set up our process to execute the correct hook when the appropriate conditions are met.

Apex Code

Create Live Session - HookCreateScheduledLiveSession

This class will make a call to the ScreenMeet API to create a new ScreenMeet Session with the type of 'live' for an audio/video call.

public with sharing class HookCreateScheduledLiveSession {
    //@InvocableMethod allows Flow Processes to use this method
    @InvocableMethod(label='SM Schedule Future Call')
    public static void demoAppointmentProcessHook(List<ServiceAppointment> apptLst) {
        //We will receive the apptList object from Flow
        System.debug('Appointment Created - Creating SM Session ' + apptLst);
        for (ServiceAppointment apt : apptLst) {
            //We will look up the owner of the appointment so that we can create the live call on their behalf with the service account
            User owner = [SELECT Name FROM User WHERE Id = :apt.OwnerId];
            //format the desired date into an ISO Date String
            String isoDate = (String)JSON.deserializeUntyped(JSON.Serialize(apt.SchedStartTime));
            System.debug('CREATING APPOINTMENT FOR DATE:' + isoDate);
            //Perform the @future callout to the ScreenMeet API
            futureCreateScheduledSessionCallout(apt.id, 'Live Call for Appointment ' + apt.AppointmentNumber, apt.OwnerId, owner.Name,  isoDate);
        }
    }

    //Asyncronous @future callout that does ScreenMeet API call
    @future(Callout=true)
    public static void futureCreateScheduledSessionCallout(String id, string label, string ownerId, string ownerName, string isoDate) {
        screenmeet.ScreenMeetAPI.ScreenMeetSessionParams newSession = new screenmeet.ScreenMeetAPI.ScreenMeetSessionParams(
            'live', //session type
            id, //parentObjectId - in this case, the Service Appointment ID
            'serviceappointment', //owner object type which will show back up in the ScreenMeet Live Session table
            ownerId, //owner id to enable ScreenMeet ACL functionality
            label, //the description of the call
            ownerName //name of the owner
        );
        //the actual REST callout
        //This avoids running API callouts during test execution which will fail because no real data is available
        if (!Test.isRunningTest()) {
              screenmeet.ScreenMeetApi.scheduleSession(newSession, isoDate);
        }
        System.debug('Scheduled appointment successfully: ' +  newSession);
    }
}


Reschedule Live Session - HookRescheduleLiveSession

Sometimes we have to re-schedule our appointments. In this case, we will also want to reschedule our Live Call together with the appointment.

public with sharing class HookRescheduleLiveSession {
    @InvocableMethod(label='SM Update Scheduled Call')
    public static void demoAppointmentProcessHook(List<ServiceAppointment> apptLst) {
        System.debug('Appointment UPDATE - UPDATING SM Session' + apptLst);
        for (ServiceAppointment apt : apptLst) {
            //prepare new ISO Date String with new Appointment scheduled start time
            String isoDate = (String)JSON.deserializeUntyped(JSON.Serialize(apt.SchedStartTime));
            screenmeet__Live_Session__c smSession = [SELECT Id, screenmeet__Session_Id__c from screenmeet__Live_Session__c where Id = :apt.ScreenMeet_Live_Session__c];
            futureRescheduleCallout(smSession.screenmeet__Session_Id__c, isoDate);
        }
    }

    
    @future(Callout=true)
    public static void futureRescheduleCallout(String SmSessionId, string isoDate) {
        //Make call to ScreenMeet API
        //This avoids running API callouts during test execution which will fail because no real data is available
        if (!Test.isRunningTest()) {        
            screenmeet.ScreenMeetApi.rescheduleRemoteSession(SmSessionId, isoDate);
        }
        System.debug('Rescheduled live session ' + SmSessionId + ' for ' + isoDate);
    }
}

Cancel Live Session - HookCancelScheduledLiveSession

Finally, an example showing how to cancel a live session.

public with sharing class HookCancelScheduledLiveSession {
    @InvocableMethod(label='SM Cancel Scheduled Call')
    public static void demoHookCancelScheduledLiveSession(List<ServiceAppointment> apptLst) {
        System.debug('Appointment UPDATE - CLOSING SM Session' + apptLst);
        for (ServiceAppointment apt : apptLst) {
            //find the linked ScreenMeet Live Session object
            screenmeet__Live_Session__c smSession = [SELECT Id, screenmeet__Session_Id__c from screenmeet__Live_Session__c where Id = :apt.ScreenMeet_Live_Session__c];
            futureCloseSessionCallout(smSession.screenmeet__Session_Id__c, apt.Id);
        }
    }
    
    @future(Callout=true)
    public static void futureCloseSessionCallout(String SmSessionId, String svcAptId) {
        screenmeet.ScreenMeetApi.closeRemoteSession(SmSessionId);
        //remove the related object reference from the appointment lookup when we cancel the appointment
        if (!Test.isRunningTest()) {
            ServiceAppointment apt = [SELECT Id, ScreenMeet_Live_Session__c from ServiceAppointment where Id = :svcAptId];
        }
        //remove reference to closed object
        apt.ScreenMeet_Live_Session__c = null;
        update apt;
        System.debug('Close ScreenMeet live session ' + SmSessionId + ' for appt ' + svcAptId);
    }
}

Update ServiceAppointment via Trigger - LinkScheduledServiceAppointment

Because of the asynchronous nature of interacting with the ScreenMeet API, we won't instantly have the newly created ScreenMeet Session object to update our ServiceAppointment object. Instead, we will add a trigger to the ScreenMeet Live Session table to update ourServiceAppointment.

Adding a Custom field to ServiceAppointment
NOTE: In order to track whether a ServiceAppointment has a live session associated with it or not, we are going to add two custom Lookup fields to ServiceAppointment called ScreenMeet_Live_Session__c and ScreenMeet_Live_Session_URL__c.
trigger LinkScheduledServiceAppointment on screenmeet__Live_Session__c (after insert) {   
    if (Trigger.isInsert) {
        for (screenmeet__Live_Session__c ls: Trigger.new) {
            //only associate to service appointment when the parent object is a service appointment and the status is scheduled.
            if (ls.screenmeet__parentObjectType__c == 'serviceappointment' && ls.screenmeet__Status__c == 'scheduled') {
                System.debug('New service appointment being created');
                ServiceAppointment svcApt = [SELECT ScreenMeet_Live_Session__c, Id FROM ServiceAppointment where Id = :ls.screenmeet__parentObjectId__c];
                svcApt.ScreenMeet_Live_Session__c = ls.Id;
                svcApt.ScreenMeet_Live_Session_URL__c = ls.screenmeet__user_url__c;
                update svcApt;
                System.debug('Associated newly created SM session ' +  svcApt.id + ' with SVC Appointment ' + svcApt.Id);
            }
        }
    }
}

Configuring Flow Process Builder

We are going to use the Process Builder from Setup to build our process to run our three Apex classes. Here is the general configuration we use for this example:

Let's take a look at what is happening our process here:

1. We have a rule based on ServiceAppointments to see if we need to Create a Live Call to execute the HookCreateScheduledLiveSession Apex code.

The rule set for creating a new session is:
SchedStartTime is NOT NULL
ScreenMeet_LiveSession__c IS NULL
Status is NOT (Canceled, Cannot Complete, Completed)
Basically, we want to make sure that there is a scheduled start time for the appointment, that no live session has already been created for this appointment, and that the status us valid.

2. We have a rule to determine if we need to reschedule the live call, which will execute HookRescheduleLiveSession.
SchedStartTime is NOT NULL AND HAS CHANGED
ScreenMeet_LiveSession__c IS NOT NULL
Status is NOT (Canceled, Cannot Complete, Completed)
This rule is similar to the first rule, but since the live call has already been created, we need to reschedule it.

3. Finally, we have a rule to determine if we need to cancel the Live Session call in case the Appointment was cancelled. This will execute the code in HookCancelScheduledLiveSession.

SchedStartTime HAS CHANGED AND IS NULL

OR (Status has changed to (Canceled, Completed, Cannot Complete) AND we have a Live Session)








Was this article helpful?