• Skip to main content
  • Skip to primary sidebar

DayBack

The Calendar You've Been Waiting For

  • Calendar
    • For Salesforce
      • DayBack Calendar for Salesforce
      • Field Service
      • Calendar Sharing in Salesforce
    • FileMaker Calendar
    • For Google Calendar
    • For Google Sheets
    • For Microsoft 365
    • For Basecamp
    • Integrations
  • Extensions
  • Pricing
  • Blog
  • Support
    • Support Options
    • Documentation
    • Documentation for DayBack Classic (older)
    • Implementation Packages
  • Contact
    • Our Mission
    • Team & Community
    • Careers
    • Contact Us
    • +1 (855) 733-3263
  • Timelines
    • Overview
    • History of the polio vaccine
    • Women’s Suffrage
    • Science Fiction
    • Your Vote in Context: the 2020 US Elections
    • History of Claris FileMaker
  • Sign In

Jul 19 2021

Prevent Resource Conflicts in Salesforce

Resource Conflicts in Salesforce

DayBack does not prevent the double-booking of resources by default. Instead, it shows you conflicts by presenting events as overlapping. But some organizations want to make sure a resource is never double-booked; this can be done by using a Custom Event Action to change the way DayBack behaves.

What constitutes a resource conflict?

Using a “Before event save” action can trigger an error message when a timed event is double-booked. And you can extend the action to include any additional criteria that constitute a conflict for you. You may exempt “pending” events, for example, or events that are marked “canceled.”

Here is what the stock actions looks like in action:

Why would I need this action since I can see any resource conflicts right there on the screen?

You’ll see an example of this in the movie above. If we type in a customer name in the text filter, it shows the events related to that customer only. We cannot see the other events associated with any other customers. When I try to schedule an event for the customer I have filtered, I wouldn’t see a conflict with an existing event for another customer because that conflicting event is currently not on screen.

Limitations

This action only works for timed events (it doens’t look at all-day events). And the action only works on one source at a time (it won’t see conflicts between events in two different calendars).

Most importantly, It only warns users when events are created or rescheduled in DayBack: if I make an event off on another Salesforce page, I won’t get a conflict warning. If I want to see a conflict warning no matter where I make the event, we’d need to do the conflict checking in the Salesforce backend as described here: Detecting Date Range Conflicts in Salesforce – Example Code.

Adding this to your DayBack

Click on the gear symbol right next to your calendar, then choose Actions/Buttons. Add the new event action and choose the action “Before Save Event” from the drop-down menu. Copy the JavaScript code below and paste it into the editor. Select the checkbox Prevent Default Action: “Yes.” It autosaves the action. Go back to the calendar, if you’re trying to schedule an event on top of another scheduled event at the same time slot, then custom event action will be triggered, and the appropriate error message will be displayed.

// SalesForce Conflict Checking v2.00

// Purpose:
// This function won't consider the AllDay Event Schedule.
// This will check for resource conflicts when creating and saving events
// the logic is to look for a record in the same table with the same resourse with any overlapping times
// if a record is found an error dialog is generated that the event can't be scheduled due to a conflict.

// Action Type: Before Event Save
// Prevent Default Action: Yes

// More info on custom Event Actions here:
// https://docs.dayback.com/article/20-event-actions

// Declare globals
var options = {}; var inputs = {};

try {

    //----------- Configuration -------------------

        // Options specified for this action
        
        // Seconds to wait to allow this action to run before reporting an error (set to 0 to deactivate)
        options.runTimeout = 8;
        // Array of account emails for whom this action will run. Leave blank to allow the action to run for everyone.
        // Example: ['[email protected]', '[email protected]']
        options.restrictedToAccounts = [];

        // Any input data for the action should be specified here

        // The currently signed in account email
        inputs.account = seedcodeCalendar.get('config').account;

    //----------- End Configuration -------------------

}
catch(error) {
    reportError(error);
}



//----------- The action itself: you may not need to edit this. -------------------


// Action code goes inside this function
function run() {
  
    //retrieve field values and names from event object for query
    var objectName = event.schedule.objectName;
    var calendarName = event.schedule.name;
    var resourceField = event.schedule.fieldMap.resource;
    var startField = event.schedule.fieldMap.start;
    var endField = event.schedule.fieldMap.end;
    var start;
    var end;
    
    if(!event.schedule.allowAllDay) {
        start = dbk.timezoneTimeToLocalTime(moment(editEvent.start).format());
        end = dbk.timezoneTimeToLocalTime(moment(editEvent.end).subtract(1,'days').format());
    }
    else {
        start = dbk.timezoneTimeToLocalTime(moment(editEvent.start)).format();
        end = dbk.timezoneTimeToLocalTime(moment(editEvent.end)).format();
    }

    var eventId = editEvent.eventID ? editEvent.eventID : false;

    //retrieve our canvas client object for authentication
    var client = fbk.client();

    //retrieve our canvas context object for REST links/urls
    var context = fbk.context();

    //retrieve the query URL from context
    var url = context.links.queryUrl;

    //SOQL Select Statement Fields;
    var select = 'SELECT+Id+FROM+' + objectName;

    //SOQL Where Clause
    var where = '+WHERE+' + resourceField +'+=+\'' + editEvent.resource[0] + '\'+AND+' + startField + '+<+' + encodeURIComponent(end) + '+AND+' + endField + '+>+' + encodeURIComponent(start) + '+';

    if (eventId) {
        where = where + 'AND+Id+!=+\'' + eventId + '\'';
    }

    //SOQL query
    var query = select + where;

    //final URL for GET
    var finalUrl = url + '?q=' + query;

    //build settings object for Ajax call to Salesforce
    var settings = {};
    settings.client = client;
    settings.contentType = 'application/json';
    settings.success = processResult;

    //Use canvas function to query
    Sfdc.canvas.client.ajax(finalUrl, settings);

    function processResult(data) {
        if (data.status == 200) {
            
            if (data.payload.totalSize == 0) {
                //no errors and no results, no conflict found
                confirmCallback();
            }
            else {
                //no errors, but results found. we have a conflict
                cancelTimeoutCheck();
                
                utilities.showModal('Conflict Error', 'There is a conflict in the ' + calendarName + ' calendar and your event can not be scheduled','OK', cancelFunction);
            }
        }
        else {
            //error which could result in failing the events to be saved.
            cancelTimeoutCheck();
            utilities.showModal('Error checking for conflicts', 'The query for conflicting events returned an error: ' + data.payload[0].errorCode + '. ' + data.payload[0].message,'OK', confirmCallback);
        }
    }

    function cancelFunction() {
        cancelCallback();
    }

}


//----------- Run function wrapper and helpers - you shouldn't need to edit below this line. -------------------

// Variables used for helper functions below
var timeout;

// Execute the run function as defined above
try {
    if (!options.restrictedToAccounts || 
        !options.restrictedToAccounts.length || 
        (options.restrictedToAccounts && options.restrictedToAccounts.indexOf(inputs.account) > -1)
    ) {
        if (action.preventDefault && options.runTimeout) {
            timeoutCheck();
        }
        run();
    }
    else if (action.preventDefault) {
        confirmCallback();
    }
}
catch(error) {
    reportError(error);
}

// Run confirm callback when preventDefault is true. Used for async actions
function confirmCallback() {
    cancelTimeoutCheck();
    if (action.callbacks.confirm) {
        action.callbacks.confirm();
    }
}

// Run cancel callback when preventDefault is true. Used for async actions
function cancelCallback() {
    cancelTimeoutCheck();
    if (action.callbacks.cancel) {
        action.callbacks.cancel();
    }
}

// Check if the action has run within the specified time limit when preventDefault is enabled
function timeoutCheck() {
    timeout = setTimeout(function() {
        var error = {
            name: 'Timeout',
            message: 'The action was unable to execute within the allotted time and has been stopped'
        };
        reportError(error, true);
    }, (options && options.runTimeout ? options.runTimeout * 1000 : 0));
}

function cancelTimeoutCheck() {
    if (timeout) {
        clearTimeout(timeout);
    }
}

// Function to report any errors that occur when running this action
// Follows standard javascript error reporter format of an object with name and message properties
function reportError(error) {
    var errorTitle = 'Error Running Custom Action';
    var errorMessage = '<p>There was a problem running the action "<span style="white-space: nowrap">' + action.name + '</span>"</p><p>Error: ' + error.message + '.</p><p>This may result in unexpected behavior of the calendar.</p>'
    if (action.preventDefault && timeout) {
        confirmCallback();
    }
    else {
        cancelCallback();  
    }
    
    setTimeout(function() {
        utilities.showModal(errorTitle, errorMessage, null, null, 'OK', null, null, null, true, null, true);
    }, 1000);
}

Conclusion

This Custom Event Action is very flexible to prevent the different kinds of double-booking in DayBack calendar. For more on resource scheduling in DayBack, including more videos, check out resource scheduling in our docs.

We hope this helps make your resource scheduling a little easier.

Written by John Sindelar · Categorized: Dev, Salesforce · Tagged: Custom Actions, Resource scheduling, Salesforce

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

Search

Latest Posts

  • Memory is Making
  • Add Notes and Comments to Events
  • Closed Through the New Year
  • Background Gradients on Horizon View
  • Cut and Paste Rescheduling

Pinned Posts

  • Scarcity: the Science of Resource Scheduling
  • Calendars Tell Stories
  • Time Shame – Plan Your Day Like a Road Trip
  • We Can’t See Late
  • You’re Calendar’s Not a Poster

  • Facebook
  • Instagram
  • LinkedIn
  • Twitter
  • Vimeo

© SeedCode, Inc. 2013–2023
+1 (855) 733-3263
who shot this?

X

View Details
Keep me informed
Which calendar sources interest you?
Interested in a calendar source we haven't listed? Have a question for us? Please let us know.
Loading