BAT

by Gisle Hannemyr

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:

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).

BAT uses the FullCalendar JavaScript library to display availability:

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.

redflagIf 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.

redflagIn 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):

Note that the following modules are also included in the BAT project, but should initially be disabled:

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 BAT » Configuration » Fullcalendar and configure the license for Scheduler. Provided the system you're building is free software, you can use GPL.

Finally, check that you've got all the required components in place. These confirmation messages should appear in the Status report:

bat_setupok.png

Also navigate to BAT from the administration menu, and check that you have the following sub-menus in place:

bat_setupok2.png

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

  1. Navigate to BAT » Configuration » Type Bundles
  2. Add type bundle “Rooms”.
  3. 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:

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:

  1. Navigate to BAT » Events » Event types
  2. 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 BAT » Events » Event types and click on the manage states-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.

bat_06.png

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.

bat_01.png

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:

  1. Navigate to BAT » Events » Event types
  2. 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.
  3. Click the "Manage fields" tab. There is already a field labeled "Unit" with machine name event_bat_unit_reference.
  4. Add an integer (or commerce price) field labeled "Cost" (machine name field_cost) to hold the cost to rent the room.
  5. For now, leave everything else as defaults, and save settings.
  6. Navigate to BAT » Events » Event types
  7. Edit "Room cost"
  8. Under "Events", select field_cost as the default Room cost field.
  9. 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 BAT » Configuration » Type Bundles and click on the manage fields-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 BAT » Configuration » Type Bundles and click on the edit-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:

  1. Navigate to BAT » Configuration » Type Bundles.
  2. Click on "Manage fields" for Rooms.
  3. Add the field "Availability" and make it a "BAT Event State Reference" (this is always used for fixed state event).
  4. For "Room Settings", make the event type "Room availability".
  5. Save settings
  6. Navigate to BAT » Configuration » Type Bundles.
  7. Click on "Edit" for Rooms.
  8. Set field_availability for the default room availability field.
  9. 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.:

To add a default cost field, go through the following steps:

  1. Navigate to BAT » Configuration » Type Bundles.
  2. Click on "Manage fields" for Rooms.
  3. Add an integer field named "Cost2".
  4. Click on "Save" and then on "Save field settings"
  5. On the next screen, keep defaults and click on "Save settings"
  6. Navigate to BAT » Configuration » Type Bundles.
  7. Click on "Edit" for Rooms.
  8. Set field_cost2 for the default room cost field.
  9. Save BAT Type Bundle

To change the defaults, you navigate to BAT » Events » Add an Event and add a "Room cost" or "Rooms Availability" event.

bat_07.png

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.

  1. Navigate to BAT » Configuration » Types.
  2. Click on "Add a Type", and add "Room".
  3. Set the autocomplete “Availability” field to “Available”.
  4. Set the “Cost2” field to an integer cost (e.g. “700”).
  5. Click on “Save Type”.

The result should look like this:

bat_02.png

Manage units

Now you can go ahead and manage bookable units (i.e. rooms).

  1. Navigate to BAT » Unit management.
  2. Pick the unit type you're interested in the column "Operations" (currently only "Room" exists) and click on "Units".
  3. 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 BAT » Admin » Unit management and click on the link “Units”. You now get an overview of all your units:

bat_04.png

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 BAT » Unit management » Manage Room Availablity you should be able to see all the rooms and all the time slots. Since no room is booked yet, all slots are available.

bat_03.png

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.

bat_07.png

To create an event through the Event Management interface, navigate to BAT » Events » Add an Event and add a "Rooms Availability" event.

bat_08.png

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 BAT » Unit management » Manage Room Availablity 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.

bat_09.png

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:

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:

  1. BAT Calendar Reference: How to set order of rooms in Month View?.

redflagDo 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 BAT » Configuration-menu: BAT Booking Types and BAT Booking.

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.

  1. The Fullcalendar

In order to use BAT in the Tolfa CMS, I need to do three things:

  1. Display availablity in a Tolfa-style calendar.
  2. Do my own booking.
  3. 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:

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:

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].