The Advanced Booking Rule is no longer used, use Workflows instead.
Advanced Booking Rules provide a means for the implementation of almost anything required. They allow the configurer to write a Booking Rule using Java that will be run using BeanShell. This means it requires a programmer to create an Advanced Booking Rule. This documentation includes some example Booking Rules, so that a programmer may be able to produce the effect they want from what's here, but this is not a complete reference to the functionality available inside an Advanced Booking Rule. A complete programmer's API documentation may be made available at some time, but for now, to create an Advanced Booking Rule, either try to adapt the examples here, or contact us for help.
When creating an Advanced Rule a user needs to define how Advanced Rules will work with repeat bookings. Normally rules are run once for each instance of a repeat booking.
Option |
Description |
Run for each repeating instance |
The Rule is given a copy of the repeat booking. Consequently, if the rule modifies this copy, changes made to it will not be saved to the database nor seen by subsequently run rules. |
Run once |
The rule is given the original repeat booking, and changes the Rule makes to the booking will then be persisted and also available to subsequent Rules. |
Note: that for repeat bookings, advanced Rules marked as being run once will always be run before all other Rules regardless of requested Rule execution order.
When your Booking Rule is run, the following local variables will be set in the BeanShell environment:
Name |
Class |
Description |
biskitDAO |
com.springsolutions.biskit.persistence.HibernateBiskitDAO |
Interface to the Calpendo database. |
biskitDefs |
com.springsolutions.biskit.core.def.BiskitDefStore |
Provides access to all the Biskit definitions. |
booking |
com.springsolutions.calpendo.domain.Booking |
The booking being created or the new version of the booking being updated. Identical to newBooking. |
newBooking |
com.springsolutions.calpendo.domain.Booking |
The booking being created or the new version of the booking being updated. Identical to booking. |
oldBooking |
com.springsolutions.calpendo.domain.Booking |
The original version of the booking for an update, and null otherwise. |
realUser |
com.springsolutions.calpendo.domain.CalpendoUser |
The user making the change. |
user |
com.springsolutions.calpendo.domain.CalpendoUser |
The effective user making the change. This can be different from the real user when running with The Booking Rule Validator. |
isUpdate |
Boolean |
True if the user is making an update, and false if a booking is being created. |
result |
com.springsolutions.calpendo.domain.rule.RulesResult |
The result that must be filled in by the Booking Rule. |
rule |
com.springsolutions.calpendo.domain.rule.AdvancedRule |
The Booking Rule itself. Sometimes you may want to insert the Booking Rule name into the error message shown to a user. |
The RulesResult class, as represented by local variable result, is the way to pass information back to Calpendo. It has the following API:
RejectionLevel is an enum as follows:
package com.springsolutions.calpendo.domain.rule; |
Example: Reject Bookings More Than 6 Weeks Into The Future
Here is an example of an Advanced Booking Rule that will reject bookings made more than 6 weeks into the future. Note that this can be done both with a Simple Booking Rule and also (better still) with Time Templates. However, this serves as an example of how to use advanced Booking Rules.
import com.springsolutions.calpendo.domain.*; |
Example: Enforcing Project Resource Settings
Calpendo uses Hibernate for accessing its database. The database can be accessed directly by obtaining a Hibernate SessionFactory as shown by this example. If this is done, make sure that the Hibernate session is closed. This Booking Rule does the following:
•Only run for bookings that have a project associated
•Reject the booking if trying to book for a resource that's not represented by the Project's Resource Settings
•Reject the booking if it is for a time after the project's finish property, where finish is a dynamic property.
•Reject the booking if its duration is more than the minutesPerSession property of the Project's Resource Settings
•Use Hibernate to count the total number of Approved and Requested bookings for the project, and reject the booking if there would be more bookings than the numberOfSessions property of the Project's Resource Settings
These tasks are more easily done using the dedicated Booking Rule Types, but this Booking Rule serves as a good example of how to interact with the Calpendo database directly through Hibernate.
import com.springsolutions.calpendo.domain.*; |
Example: Enforce 15 Minute Gaps Between Bookings
This Booking Rule will ensure that there is always a 15 minute gap between bookings. If using this Booking Rule, it may be a good idea to use the Rule's Applies To --> Resources tab to make sure that it only applies to the appropriate resources. Before using this please look at the standard Booking Interval Rule as this may be much easier to implement what you want.
import com.springsolutions.biskit.core.Biskit; import com.springsolutions.calpendo.domain.Booking; import com.springsolutions.calpendo.domain.rule.RejectionLevel; import com.springsolutions.exprodo.core.server.HibernateUtil; import com.springsolutions.timeRepeating.domain.RepeatUtil; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; import org.hibernate.Session; import org.hibernate.Query;
session = HibernateUtil.getSessionFactory().openSession(); sqlFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try { Calendar cal = Calendar.getInstance(); cal.setTime(booking.getDateRange().getStart()); cal.add(Calendar.MINUTE, -15); Date start = cal.getTime(); cal.setTime(booking.getDateRange().getFinish()); cal.add(Calendar.MINUTE, +15); Date finish = cal.getTime();
String hql = "from " + Booking.TYPE + " b where not (b.dateRange.start > '" + sqlFormatter.format(finish) + "' or b.dateRange.finish < '" + sqlFormatter.format(start) + "') and b.resource.id=" + booking.getResource().getPrimaryKey() + " and b.status != 'CANCELLED' " + " and b.status != 'DENIED'";
searchResult = session.createQuery(hql).list();
found = RepeatUtil.expandRepeatables(searchResult, start, finish); boolean doubleBooking=false, bufferInfringed=false; bookingStart = booking.getDateRange().getStart().getTime(); bookingFinish = booking.getDateRange().getFinish().getTime();
for (Biskit b : found) { Booking clash = (Booking) b; dr = clash.getDateRange(); if (b.getPrimaryKey() == booking.getPrimaryKey() || dr.getStart().getTime() >= finish.getTime() || dr.getFinish().getTime() <= start.getTime()) continue;
if (dr.getStart().getTime() >= bookingFinish || dr.getFinish().getTime() <= bookingStart) bufferInfringed = true; else doubleBooking = true; }
String msg; if (doubleBooking) result.setMessage("Double bookings are not allowed"); else if (bufferInfringed) result.setMessage( "You must leave a gap of 15 minutes between bookings");
if (doubleBooking || bufferInfringed) result.setRejectionLevel(RejectionLevel.REJECT); } finally { session.close(); }
|