In the previous blog post you learned how to call the The Weather Company Data service on Bluemix via Apex and how to display its data within a custom Salesforce Lightning component. We’re now taking this a step further by implementing weather data into a time-sensitive business process, using either Process Builder or scheduled Apex.
Master Builders is a company that produces and fits exteriors like windows. Whenever an opportunity is set to “Closed – Won” a Process Builder flow kicks off and schedules the next available worker for a fitting appointment. In the past the automated scheduling led to cancelled appointments because of bad weather conditions. Master Builders wants to enhance the process and use weather data to optimize the scheduling for higher customer satisfaction.
In this example, we use a next-day weather forecast to trigger action when conditions are likely to cause a cancellation. This is one of several possible applications of weather forecasts to field service use cases. We are looking forward to another example, where an extended forecast is used to minimize the need for last-minute cancellations by smarter initial scheduling, coming soon from our colleagues at The Weather Company. Stay tuned for further details. Now on to the next-day example for Master Builders.
This is a simplified version of the flow for the opportunity object:
When the opportunity stage is set to “Closed-Won,” a custom record is created for the fitting appointment. Part of the record creation is a formula-calculated fitting date.
Based on the business requirements, the following checks and actions will be implemented:
Two options are available to fulfill the requirement for time-based checks:
Process Builder has the capability to invoke an Apex method that is annotated with @InvocableMethod
. Because a class can have only one invocable method at a time, we’re using a dedicated class IBMWeather_ProcessBuilder for storing the method.
public class IBMWeather_ProcessBuilder { @InvocableMethod public static void checkWeatherBeforeFittingAppointment(List<Fitting_Appointment__c> appts) { for (Fitting_Appointment__c appt : appts) { IBMWeather_Controller.checkWeatherForecastsForFittings(appt.Account__c); } } }
Code explanation:
@InvocableMethod
is mandatory to make the method visible for Process Builder.Fitting_Appointment__c
records is determined by the declarative selections within Process Builder.With this setup, we can use the method as a declarative action. See how in this example flow for new and changed fitting appointment objects:
The second option for this time-sensitive task is using a scheduled Apex class. This approach allows a developer to separate the time-check from the process of appointment creation. It can also be combined with other time-related tasks for the Fitting_Appointment__c
object.
global class IBMWeather_Scheduled implements Schedulable { global void execute(SchedulableContext ctx) { List<Fitting_Appointment__c> appts = [SELECT Account__c FROM Fitting_Appointment__c WHERE Fitting_Date__c=TOMORROW]; for (Fitting_Appointment__c appt : appts) { IBMWeather_Controller.checkWeatherForecastsForFittings(appt.Account__c); } } }
Code explanation:
Schedulable
interface to make it schedulable.execute
method is called once the scheduled time is reached.This class can then be scheduled by a Salesforce administrator using the Apex scheduling UI.
While the options for identifying scheduled fitting appointments are different, they share the same method(s) for filtering the weather conditions.
@future(callout=true) public static void checkWeatherForecastsForFittings(Id accountId) { IBMWeather_Forecast[] forecasts = getWeather3DayForecasts(accountId); // We only need tomorrows weather in this implementation String message = evaluateBadWeatherConditions(forecasts.get(1)); if (!message.equals('')) { ConnectApi.FeedElement fe = ConnectApiHelper.postFeedItemWithMentions( Network.getNetworkId(), accountId, message); } }
Code explanation:
@future(callout=true)
allows us to execute asynchronous, non-blocking, REST callouts.IBMWeather_Forecast
object array contains tomorrow’s weather forecast in it’s second element.evaluateBadWeatherConditions
method returns a non-empty string.The weather data contains information about temperature, precipitation, wind strength, and more. We’re using that data to filter for rainy and windy weather conditions to fulfill the business requirement. If inclement weather conditions are identified, a meaningful message gets returned for use in the Chatter post.
private static String evaluateBadWeatherConditions(IBMWeather_Forecast forecast) { Boolean withRain; Boolean withWind; if (forecast.day.precipitation>35) { // precipitation is higher than 35% withRain = true; } if (forecast.day.wspd>5) { // wind is stronger than 5 withWind = true; } if (withRain && withWind) { return 'Holy Moly - it will be rainy and stormy!'; } else if (withRain) { return 'Some rain will come down!'; } else if (withWind) { return 'Strong winds are expected!'; } return ''; }
This post depicts how to use weather-related data, delivered by The Weather Company Data service, in a business process. You also learned about different options for time-based actions using scheduled Apex or an invocable method in conjunction with Process Builder. The source code and an installation link for an unmanaged package is available on my GitHub repo.
Check out our Trailhead modules about Process Automation, Asynchronous Apex, and Apex REST Callouts to learn more about the shown approaches. General information about the Salesforce and IBM partnership can be found on our microsite here.
René Winkelmeyer is a senior developer evangelist at Salesforce. He focuses on enterprise integrations, mobile, and security with the Salesforce Platform. You can follow him on Twitter @muenzpraeger.