Reservation Scripts
Overview
Reservation scripts are a powerful tool to implement custom rules for allowing or disallowing reservations and for dynamically modifying reservations on the fly. Reservation scripts will typically either return an Exception when a reservation cannot continue as is or a Result for when a reservation can continue as but, optionally, some additional UI elements may need updating.
Exceptions
Exceptions are the one way to abort a sneq script from anywhere within the script, including nested functions, and return some value.
For reservations and requests, the return value of the Exception determines how a script failure is reported to the user.
As a string
If the Exception is a string, the conflict message will be set to that string.
1return Exception("Hello world")

Tip: Avoid punctuating the last sentence of your exception with anything other than a period, because by default all conflicts will have a period appended to them if one is not present as the last character.
As a dictionary
The dictionary form of an Exception is used to control behaviour in the reservation/request modal. The dictionary should be in the following form:
1{2 'conflict'?: <str>,3 'alert':? {4 'title': <str>,5 'text': <str>,6 'confirmText'?: <str>,7 'type'?: <str>, # 'error', 'info', 'question', 'success', or 'warning'8 },9 'times'?: {10 'start': <datetime>,11 'end': <datetime>,12 'lockStart': <bool>,13 'lockEnd': <bool>,14 'lockStartPermanent': <bool>,15 'lockEndPermanent': <bool>,16 },17}
conflict
If the conflict
key is set and a string, the conflict will be set in the reservation/request modal.
alert
If the alert
key is set to a dictionary as above, an alert will be displayed to the user.
1return Exception({2 'conflict': 'foo',3 'alert': {4 'title': 'Title goes here',5 'text': 'Text goes here',6 'confirmText': 'confirmText',7 'type': 'success',8 },9})

Date/time manipulation
Exceptions allow you to lock the date and time on your reservation. It also allows you to set them. Care must be taken when setting the start and end datetimes so that the reservation does not go into an infinite loop. For example, two scripts both setting start dates could easily send the booking modal into an infinite loop of conflict checks.
In the times
value, start
and end
refer to datetime objects that are used to set the start and end date.
lockStart
and lockEnd
are used to lock the start and end times once, until the current conflict is cleared.
lockStartPermanent
and lockEndPermanent
are used to lock the start and end times indefinitely, and these locks will not change when another conflict check is made, for example, when a user changes the resource.
Below is an example that sets the start and end date to be January 1, 2021 at 12AM and February 1, 2021 at 12 AM, then locks the times to prevent the user from changing them.
1start = datetime.from_date_and_time(2 year=2021,3 month=1,4 day=1)5end = datetime.from_date_and_time(6 year=2021,7 month=2,8 day=1)910# Do not infinite loop conflict checking if the start and end times11# are what they should be.12if reservation['start'] == start and \13 reservation['end'] == end:14 return True1516# If they aren't what they should be, set them to what they should17# be and then lock them.18return Exception({19 'times': {20 'lockStartPermanent': True,21 'lockEndPermanent': True,22 'start': start,23 'end': end,24 },25})
Upon testing this script, you will see output like this:

Attach the script to a resource, then try on the calendar. You will see that the time has been fixed as per the script.

Resource manipulation
The list of resources can be set by returning an Exception dict
that contains the key "reservables".
1return Exception({2 'reservables': [3 {4 'reservable_id': <str>, # Required5 'units'?: <dec> or <int>, # >= 1, default is 16 'rate_id'?: <dec> or <int>, # Integer for the rate ID of choice7 },8 ...9 ],10})
Note and purpose manipulation
You can set the value of the reservation's note and purpase by returning an Exception dict
with "purpose" and "note" fields. Furthermore, you can lock the purpose or note from editing by also returning "lockPurpose" and "lockNote".
1return Exception({2 'lockNote': <bool>,3 'lockPurpose': <bool>,4 'note': <str>,5 'purpose': <str>,6})
Return Results
Results of a script may also modify the state of a reservation when no conflict exists. You can access these functions by returning a dictionary.
true
If a reservation script decides that a reservation can proceed as is, simply return True
.
disclaimer_resource
String with markdown syntax. Sets a disclaimer below the resource in the reservation booking modal. The first disclaimer found for the resource will be the one shown to the user in the case that there are multiple resource disclaimers present from multiple scripts.
What resource this disclaimer applies to is determined by which resource the script is attached to. For example, if the reservation is for two resources but the script is only attached to one of them, the disclaimer will only show for the one the script is attached to.
Example:
1return { 'disclaimer_resource': '## foo' }
disclaimer_top
String with markdown syntax. Sets a disclaimer above the list of resources in the reservation booking modal. The first script output with disclaimer_top
set will be the one shown to the user in the case that there are multiple top-level disclaimers present from multiple scripts.
Example:
1return { 'disclaimer_top': '## foo' }
lockNote and lockPurpose
If you are setting the note or purpase with an exception it can be useful to always lock the value afterwards or when editing. This can be done without throwing an exception by returning an object with one or both of these keys set to true
. Typically a reservation script would return an exception with a note or purpose value and a lock if the purpose needs to be set. If the purpose does not need to be changed, simply return the instruction to lock the fields so that no additional editing can take place.
1return {2 'lockNote': <bool>,3 'lockPurpose': <bool>,4}