An update on Rooms
It’s been a bit over five weeks when we announced that we were developing a room booking solution for Drupal 7. Well, it’s been a busy few weeks and we are happy to report that we are very close to a public release. With the main architectural components in place I wanted to take this chance to introduce some of the guiding concepts and decisions for Rooms as well as some screenshots.
The main element of our applications are of course the things that we book - what we are provisionally calling Bookable Units or simply Units. These are entities in the Drupal 7 sense which means they can be extended using the Field API. They have, however, a number of native properties (i.e. specific to their own table in the database). These are:
- Name - the name of the room, villa or any other thing that will be booked on a per-night basis
- Base Price - the default price for the room on a nightly basis
- Default State - the default bookable state (more about states in a bit)
- Sleeps - how many can sleep in a bookable unit
- Data - extra data such as bed distribution, cots, etc
Units have types, so you would expect a hotel to define types for Basic Rooms, Deluxe Suites or if you are managing a number of rental villas you could define different types of Villas, etc.
Once you have types you can create actual instances of Units. In order to make things simpler for places with many units you can easily create multiple units at once (e.g. give me 40 standard rooms).
Once you create a Unit you can manage its availability. From the start we wanted to support a number of different situations here so that Rooms could grow to become a proper property management tool. So our requirement was to support Units that can be in any number of different situations. They may be available to book immediately, book on request, unavailable, actually booked, under restoration, etc.
In order to accommodate for this we have the concept of an availability state. A unit gets assigned states on a per night basis and these states are saved in the database. States are simply IDs and currently we are blocking some state IDs for the various states that are not directly tied with a booking order while any IDs not blocked actually point to a booking order that we can look up to get client details, etc.
So an availability search in the broader sense is finding a room that for the range of dates we are interested in is only in states that we are interested in - not simply available for booking. The code looks like this:
$rc = new UnitCalendar($unit->unit_id);
$rc->stateAvailability($start_date, $end_date, array(AVAILABLE))
The stateAvailability function accepts a start date and end date and an array of states. If the room is in any state that is not within the array of states we request it will return FALSE.
Availability can be updated directly on a per room basis while we are working on managing multiple rooms at once.
Pricing Management was an interesting one. We initially thought we would simply use something like Rules to set prices for seasons, etc. Turns out hotels need something that is both more powerful (in terms of flexibility of price definition) but and also simpler in terms of no need for rules to interact.
In the cut-throat world of online bookings it is essential that a hotel is able to react immediately. Rules like “Room costs 200 Euro per night over August” need to efficiently work alongside needs like “I need to immediately drop the price for the next three days” or “I want a quick special promotion”.
After mulling over it quite a bit it turns out that the simplest and most powerful concept is to say that prices are a bit like availability states. A room has a price for a night and you can set defaults or change the price across a range.
So we built a management screen that is very similar to Availability Management. The main different is that instead of setting an availability state you set a price and you actually have four operations to help you. REPLACE price will replace the current price with the amount specified, ADD will increase it, SUBTRACT will detract, while DECREASE by % and INCREASE by % will do a percentage change.
This covers the range of changes and allows accommodation owners to quickly react to changes as well as set long term values in terms of seasons.
Some smart color coding can be built in to help identify various situations (e.g. lower than base price or higher than base price).
With availability and pricing taken care of then next step was actually enabling booking. While various types of search can be envisioned the first thing we want to support is: “given a date range and a group size (and room distribution) what can the accommodation offer”.
The next step was to figure out how to cleanly integrate with Drupal Commerce.
Initially we considered creating a product that would have a variable price (defined by the Rooms Pricing functionality). We would then create a line item, set the price to the correct one given the current pricing rules and add it to the cart. That, however, created all sorts of problems and also was not a clean integration - we were tricking Commerce to behave in a way it is not yet expecting to (or at least in a way that we could not adeptly handle!).
What we are currently going with - and think is the way forward even if variable pricing does come to Commerce is a much cleaner integration. Once a user settles on a Unit to book for a Date Range we actually create a product that represents the booking of that unit for that range with the price rules current at the time of booking.
Our Booking module creates a new product type on install and adds two fields to it to represent start and end dates and booking id - and it is a product of that type that we create.
The product is then simply placed in the cart and the beauty of it is that we can then easily apply any further pricing rules (discounts, vat, etc) to the product without having to worry about strange interactions between components. Commerce will do all the heavy lifting as it expects and has been designed to do.
So a search like:
will give you all the rooms available for that period - each with a Book This Room button.
Clicking that will create a product and place it in the cart for you. Because the cart is a view we can customize this as much as we want!
There is a lot to do yet - we have great ideas about how to manage availability and pricing for multiple booking units in a single go, workflows for booking, build a distribution around the module, etc - but as we said with the main bits in place the next step is to release the code.
We are cleaning things up a bit, making sure we cross our .tpls and dot our hooks and will be committing the code to drupal.org/project/rooms next week so anyone interested can join in the fun.