BAT
This tutorial is about a family of modules called BAT (Booking and Availability Management Tools).
Table of contents
Drupal projects discussed in this chapter: BAT, BAT API, Composer Manager, Search API, Search API Database Search.
Introduction
BAT is created by room booking specialists roomify. It is a very powerful package to manage booking, availability and pricing, but it also very hard to set up correctly. The installation procedures for BAT relies extensively on scripts to download required libraries. This automates parts of the process, but leave little room for error. Make sure you understand the process before you start.
Documentation and other helpful pages:
- BAT: Official docs
- BAT: Displaying availability (calendar integration)
- BAT: Searching for Availability
- BAT: Taking bookings
- DO: Trying to understand how this module functions
- GitHub: BAT repo
Installation
Before you install BAT, make sure you have the package manager composer in place. You must also install the Drupal project Composer Manager (if this is not already done).
Make sure public://composer
is writeable by the user used to run drush (not root).
These libraries, as well as the PHP library spyc will be
installed when you run the drush make
-command after you
have installed the main BAT project. Do not install these yourself.
Do not install the Drupal FullCalendar bridge module for version 1.x of the plugin. BAT provides its own BAT Fullcalendar bridge that works with the latest versions of the library.
If you use drush to install Composer Manager, just download, do not enable it. Instead, enable from the GUI to avoid having files created that are not writeable by the web server user. If you enable this from the CLI, drush will break. If this happens, you can learn how to recover from this on Drupal SE.
To install BAT, navigate to the webroot and do the following:
$ drush dl bat -y $ drush make --no-core sites/all/modules/bat/bat.make
You will be asked if you want to create a new site in the current directory. Answer yes, it won't overwrite your present site.
In order
for the files to end up in the right places you must be in the
webroot when you give the drush make
-command. If you are positioned
somewhere else in the file hierarchy, files will be downloaded to the
wrong directory and you'll end up with two copies of some projects.
This will make your site crash and to clean up the mess, you will
need Drupal internals skills. So take care.
Also note that this script may download old versions of some
projects (in worst case this may be versions security
vulnerabilities). Make sure you check update status afterwards.
After checking that all went well, in the file system, navigate to the root directory of the BAT project and run the following command:
$ composer install
This will download and install the BAT library from its GitHub repo and install it in bat/vendor
subdirectory.
Check out that the default jQuery version for your admin theme as well as the site overall is at least 1.10. Calendars will not appear if the jQuery for the theme is too old.
Also visit /sites/default/files/composer
and if make
sure that directory is writable by the web server user. If the
files composer.json
and composer.lock
exists, make sure they also are writable by the web server user.
Make sure the following (all except BAT API come bundled with the BAT project) are enabled using drush (because composer works best with drush):
- BAT (
bat
) - BAT Event (
bat_event
) - BAT Event UI (
bat_event_ui
) – will also install: BAT Fullcalendar, BAT Unit, BAT API
Note that the following modules are also included in the BAT project, but should initially be disabled:
- BAT Booking
- BAT Booking Example
- BAT Calendar Reference
- BAT Facets
- BAT Options
Check that the directory sites/all/vendor/roomify/bat
exists below the webroot.
You should not need any components from the Rooms project (mentioned in some outdated tutorials).
Once you confirm installation, Drupal will request all the dependencies to these modules. Provided that they are all already downloaded you may simply continue. If something is missing cancel the process, download the missing modules and then continue.
Also make sure Composer Manager is enabled and
that the Composer File Directory (default is /sites/default/files/composer
, but the exact path can found under the Settings tab for Composer Manager) is
writeable by the web server user.
To download and install the BAT library, visit the Composer File Directory using the CLI and the command line and run:
$ composer update $ composer install
Navigate to license for Scheduler. Provided the system you're building is free software, you can use GPL.
and configure theFinally, check that you've got all the required components in place. These confirmation messages should appear in the Status report:
Also navigate to
from the administration menu, and check that you have the following sub-menus in place:If these confirmation messages does not appear in the status report, or ay of the sub-menus are missing, it is unlikely that the configuration will work. Unfortunatly, there currently no recipe for debugging this (beyond clearing all caches).
Setting up
Below is a step by step recipe for setting up BAT a collection of rooms to be booked by the day. By default, they all share the same availability and cost.
Create type bundle
A BAT type bundle is a Drupal entity that may have fields xxx
- Navigate to
- Add type bundle “Rooms”.
- Save BAT Type Bundle
No fields are initially present. We can now add fields (but will not do so yet).
Create event types
BAT Events are the events that our types of units can go through. As a minimum, there will be two types of events:
- availability events
- cost events
There are two types of event states: Fixed and Arbitrary:
- Fixed event states:
- Fixed event states can only have a pre-defined set of values associated with them. This allows us to define states such as “Available”, “Booked” by associating a numerical (integer) value with those labels.
- Arbitrary event states:
- Arbitrary event states can have any integer value associated with them. This is great for managing pricing over time. A pricing event can have a value assigned to it that represents the price of booking our unit over that time period.
These are the steps to create a fixed availability event:
- Navigate to
- Add an event type called “Room availability”. Tick “Fixed event status” and set “Event Granularity” to “Daily”.
Click on "Save Event type".
After the event type is created we can add fields to it that will hold the event value over a time period. For fixed event states this is a two step process.
Navigate to
and click on the -link for the event that you want to add states to.For each state you can provide a label, pick a color that will be used on calendar views and a label that will be used on the calendar. Finally, you can also define the state as blocking or non-blocking.
Add two states: “Booked” and “Available”. Make “Available” the default state by selecting its radiobutton and clicking on “Set default state”.
Corresponding to the states there is a “BAT Event State Reference” field that appear when you vist the “Manage fields” tab of the Event Type.
For arbitrary event states you simply add a field that will hold the event value and then indicate what field that is so BAT can use it. For example for a pricing type event we would:
- Navigate to
- Add an event type called "Room cost". Do not tick "Fixed event status". Set "Event Granularity" to the same as the avilability event (i.e. "Daily"), and save event type.
- Click the "Manage fields" tab. There is already a field labeled "Unit" with machine name
event_bat_unit_reference
. - Add an integer (or commerce price) field labeled "Cost" (machine name
field_cost
) to hold the cost to rent the room. - For now, leave everything else as defaults, and save settings.
- Navigate to
- Edit "Room cost"
- Under "Events", select
field_cost
as the default Room cost field. - Save Event type
Events are Drupal entities, and can be extended by adding fields just like any Drupal entity.
Setting default values
We don't want to create events for every single point in time so as to have an availability and price value associated with the rooms. Therefore BAT provides a default value event field.
A default value event field holds the value for a given type of event before any actual events are created. For rooms, these will hold the default values for Availability and Pricing. Actual events associated with the meeting rooms will modify and overwrite these default values.
To create default value event fields, navigate to
and click on the -link for the type bundle you are interested in. We can now add fields to hold default event values.For fixed state events the type of field to hold the default value is always going to be BAT Event State Reference field. Name the field "Availability". Click on "Save".
For the settings, connect it to "Event type" "Room availablity". Leave the rest at default, and click "Save settings".
Now, with the field in place you can navigate yo
and click on the -link for the type bundle you are interested in. For every type of Event you will see a drop-down that allows you to connect a field of this Type Bundle to an Event Type.Connect "Select your default Rooms Availability field" to "field_availability" and click "Save Bat Type Bundle".
Here are the required steps as a list:
- Navigate to .
- Click on "Manage fields" for Rooms.
- Add the field "Availability" and make it a "BAT Event State Reference" (this is always used for fixed state event).
- For "Room Settings", make the event type "Room availability".
- Save settings
- Navigate to .
- Click on "Edit" for Rooms.
- Set
field_availability
for the default room availability field. - Save BAT Type Bundle
Similarly to fixed state events, arbitrary state events require a default value event field. The different is that in this case it does not have to be the BAT Event State Reference field. It has to be a field, however, that holds an integer value or that we transform to an integer value. As a result, BAT only supports a specific subset of fields. I.e.:
- Integer
- Commerce Price
- Text
To add a default cost field, go through the following steps:
- Navigate to .
- Click on "Manage fields" for Rooms.
- Add an integer field named "Cost2".
- Click on "Save" and then on "Save field settings"
- On the next screen, keep defaults and click on "Save settings"
- Navigate to .
- Click on "Edit" for Rooms.
- Set
field_cost2
for the default room cost field. - Save BAT Type Bundle
To change the defaults, you navigate to
and add a "Room cost" or "Rooms Availability" event.Create unit types
With type bundles in place and connected to availablity and cost events, we're ready to create actual types of bookable units.
- Navigate to .
- Click on "Add a Type", and add "Room".
- Set the autocomplete “Availability” field to “Available”.
- Set the “Cost2” field to an integer cost (e.g. “700”).
- Click on “Save Type”.
The result should look like this:
Manage units
Now you can go ahead and manage bookable units (i.e. rooms).
- Navigate to .
- Pick the unit type you're interested in the column "Operations" (currently only "Room" exists) and click on "Units".
- Click "Add units". and the number of units to create (e.g. 9).
Now we've got a number of bookable units that share default availability and cost.
To edit, add or remove units, navigate again to
and click on the link “Units”. You now get an overview of all your units:Click on the link “Add Units” to add more units. To delete units, tick the units you want to delete and choose the operation "Delete item".
If you navigate to
you should be able to see all the rooms and all the time slots. Since no room is booked yet, all slots are available.Admin: Create bookings
The simplest way to create a booking is to create an event and set its availabilty state to "Booked". This can either be done through the Event Management interface, or programmatically.
To create an event through the Event Management interface, navigate to
and add a "Rooms Availability" event.The visual calendar picker do not let you pick dates in the past, but if you enter the dates as text, youcan do so.
Admin: View event data
If you as admin navigate to
you will be able to view event data.If you made the booking described in the previous segement, you should be able to see changed, and that Room 1 is now shown as booked from september 19th to september 25th. The date of departure is not shown on the visual calendar, because it is available for booking on that day.
As for version 7.x-1.19 of BAT, the 30 days display now defaults to hourly resolution, even if booking resulution is set to "daily", and there are other details in this setup that is sub-optinal.
For this to be useful, I need to be able to tweak the display. I've created the following support request: Where is the code that creates the timeline used by View Event Data?.
Searching for availability
The BAT Facets sub-module integrates BAT search with the Drupal Search API and the Facet API. This enables you to build a view of search results where availability search is another search facet.
Make sure the following modules are enabled:
- BAT Facets
- Search API
- Search Views
- Search API Database Search
Tutorials:
[TBA]
User: Displaying availability
The BAT Calendar Reference sub-module lets you display availability to end-users.
If you enable it you can now create a Drupal content type that includes a field of type "BAT Calender Unit Reference". It provides two display formats: "Month View" and "Timeline View".
The "Month view" displays Fullcalendar booking bars for a single month using a classic 1-week wide calendar layout, but in no particular order.
The "Timeline view" is supposed to the timeline for various stretches of time (15 slots, 10 days, month) scrollable.
I've opened the following issue:
Do not have any other calendar modules enabled when using BAT Fullcalendar. I have experienced that the Fullcalendar show up garbled when you do.
User: Create bookings
Enable the module Bat booking. This adds two items to the
-menu: and .The first step is to create a Booking Entity. The purpose of this entity is to connect an event to a booking and any information that may be associated with that booking (customer profile, order, etc). As with everything else in BAT, we can have different booking types for different scenarios.
[TBA]
Hacking BAT
BAT is probably the best room booking framework available for Drupal, but it is not perfect.
- The Fullcalendar
In order to use BAT in the Tolfa CMS, I need to do three things:
- Display availablity in a Tolfa-style calendar.
- Do my own booking.
- Connect users to bookings.
BAT APIs
There are two APIs, one in the main BAT project, and one in the BAT API project. Until I can find the time to improve the documentation, the doxygen docblocks are reproduced below.
In the main BAT project:
/** * Allows modules to deny or provide access for a user to perform a non-view * operation on an entity before any other access check occurs. * * Modules implementing this hook can return FALSE to provide a blanket * prevention for the user to perform the requested operation on the specified * entity. If no modules implementing this hook return FALSE but at least one * returns TRUE, then the operation will be allowed, even for a user without * role based permission to perform the operation. * * If no modules return FALSE but none return TRUE either, normal permission * based checking will apply. * * @param $op * The request operation: update, create, or delete. * @param $entity * The entity to perform the operation on. * @param $account * The user account whose access should be determined. * @param $entity_type * The machine-name of the entity type of the given $entity. * * @return * TRUE or FALSE indicating an explicit denial of permission or a grant in the * presence of no other denials; NULL to not affect the access check at all. */ function hook_bat_entity_access($op, $entity, $account, $entity_type) { // No example. }
In the BAT API project:
/** * Alter units index calendar. * * @param array $units */ function hook_bat_api_units_index_calendar_alter(&$units) { // No example. } /** * Alter events index calendar. * * @param array $events * @param array $context */ function hook_bat_api_events_index_calendar_alter(&$events, $context) { // No example. } /** * Alter matching units calendar. * * @param array $events * @param array $context */ function hook_bat_api_matching_units_calendar_alter(&$events, $context) { // No example. }
DB schemas
Node that there also fiels created through the GUI, such as field_cost2
.
Created by code
The following tables are created by code after xxx
bat_event_room_$ac$_$du$-$se$
These 12 tables are permutations of the following:
$ac$
- availability or cost.$du$
- duration (day, hour minute).$se$
- state or event.
bat_event
bat_events
The base table for events (i.e. bookings),
including start_date
and end_date
using ISO
data format (e.g.: 2017-07-23 00:00:00 2017-07-28
23:59:00
).
bat_event_state
Stores information about defined event states (e.g.: booked, available).
bat_event_type
Stores information about defined event types (e.g.: availability, cost).
bat_unit
bat_types
Stores information about classes of unit types (e.g. rooms).
bat_types_revision
Revisions of bat_types
.
bat_type_bundle
bat_units
Stores information about individual unit types (e.g. rooms).
bat_unit_bundle
Troubleshooting
Library errors, such as:
- “Could not load the FullCalendar Scheduler Javascript Library”
- “FullCalendar Scheduler Libraries Missing”
- “Notice: Undefined index: name in libraries_detect_dependencies() …”
without an obvious cause (e.g. libraries exist in the file system, but is not found by Drupal) may occur when a library is installed or re-installed in a way that confuses Drupal.
The simplest way to fix these is to first disable the main BAT module (this also automatically disable all dependencies):
$ drush dis bat
And then reinstall BAT as described in the chapter Installation above. (There is no need to download again if it is already in place.)
Sources: Could not load the FullCalendar Scheduler Javascript Library, Problem to install BAT.
Final word
[mumble]
Last update: 2016-09-17 [gh].