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: ['person@domain.com', 'someone@domain.com'] 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.
Leave a Reply