Easy booking availability checking with Breezbook
Here are some code samples to show what kind of availability checking is possible when attempting to make bookings or appointments using breezbook.
Request a booking with "any suitable resource"
Here is a code sample showing how to check availability for a booking that requires "any suitable resource", in this case, a room:
const room = resourceType("room");
const room1 = resource(room,
[timeslotFns.sameDay("2023-07-01", "09:00", "17:00")], [],
resourceId("room1"));
const room2 = resource(room,
[timeslotFns.sameDay("2023-07-01", "09:00", "17:00")], [],
resourceId("room2"));
const meetingService = service(
resourceRequirements(
[anySuitableResource(room)]));
const requestedBooking = bookingSpec(meetingService);
const requestedTimeSlots = [
timeslotFns.sameDay("2023-07-01", "10:00", "11:00"),
timeslotFns.sameDay("2023-07-01", "11:00", "12:00"),
timeslotFns.sameDay("2023-07-01", "13:00", "14:00"),
];
const availability = listAvailability(
[room1, room2],
[],
requestedBooking,
requestedTimeSlots
)
availability.forEach((slot) => {
const time = `${startTime(slot)} to ${endTime(slot)}`
if (slot._type === "available") {
console.log(`Slot ${time} is available`);
console.log(`\tIt uses resource : ${(bookedResources(slot))}`);
console.log(`\tThe potential capacity at this slot is ${slot.potentialCapacity.value}`)
console.log(`\tThe consumed capacity at this slot is ${slot.consumedCapacity.value}`)
} else {
console.log(`Slot ${time} is unavailable`);
}
});
This declares a resourceType
("room") and creates two rooms - room1
and room2
.
Then it creates a meetingService
which requires anySuitable
room.
requestedBooking
and requestedTimeSlots
are the means to express what service we want to check availability for, and what time slots we want to check against.
The listAvailability
takes four params:
available resources
existing bookings
the request booking spec
the time slots we want to check availability against
The function returns whether the requested booking is possible at each slot. It also states how much potential capacity is at each slot, and how much capacity is used.
As there are no existing bookings in this example, all slots are available, and we get output like this:
Slot 10:00 to 11:00 is available
It uses resource : room1
The potential capacity at this slot is 2
The consumed capacity at this slot is 0
Slot 11:00 to 12:00 is available
It uses resource : room1
The potential capacity at this slot is 2
The consumed capacity at this slot is 0
Slot 13:00 to 14:00 is available
It uses resource : room1
The potential capacity at this slot is 2
The consumed capacity at this slot is 0
What happens if there are existing bookings?
This code shows what happens if you have existing bookings. The code is very similar to the above, except this time we have two bookings in the 10:00 to 11:00
slot. As we have only two rooms, we would now expect this slot to be unavailable.
const room = resourceType("room");
const room1 = resource(room,
[timeslotFns.sameDay("2023-07-01", "09:00", "17:00")], [],
resourceId("room1"));
const room2 = resource(room,
[timeslotFns.sameDay("2023-07-01", "09:00", "17:00")], [],
resourceId("room2"));
const meetingService = service(
resourceRequirements(
[anySuitableResource(room)]));
const requestedBooking = bookingSpec(meetingService);
const requestedTimeSlots = [
timeslotFns.sameDay("2023-07-01", "10:00", "11:00"),
timeslotFns.sameDay("2023-07-01", "11:00", "12:00"),
timeslotFns.sameDay("2023-07-01", "13:00", "14:00"),
];
const booking1 = booking(
timeslotFns.sameDay("2023-07-01", "10:00", "11:00"),
meetingService);
const booking2 = booking(
timeslotFns.sameDay("2023-07-01", "10:00", "11:00"),
meetingService);
const availability = listAvailability(
[room1, room2],
[booking1, booking2],
requestedBooking,
requestedTimeSlots
)
availability.forEach((slot) => {
const time = `${startTime(slot)} to ${endTime(slot)}`
if (slot._type === "available") {
console.log(`Slot ${time} is available`);
console.log(`\tIt uses resource : ${(bookedResources(slot))}`);
console.log(`\tThe potential capacity at this slot is ${slot.potentialCapacity.value}`)
console.log(`\tThe consumed capacity at this slot is ${slot.consumedCapacity.value}`)
} else {
console.log(`Slot ${time} is unavailable`);
}
});
And indeed we get the expected output:
Slot 10:00 to 11:00 is unavailable
Slot 11:00 to 12:00 is available
It uses resource : room1
The potential capacity at this slot is 2
The consumed capacity at this slot is 0
Slot 13:00 to 14:00 is available
It uses resource : room1
The potential capacity at this slot is 2
The consumed capacity at this slot is 0
Requesting a specific resource
There are cases where you want to override the resource allocation with a specific resource. For example, a user might want to book a personal training session with a specific personal trainer, rather than just get a random one.
This code shows the use of resourceCommitment
in the requestedBooking
to override the service stating that it requires anySuitableResource(room)
, in favour of using room2`:
const room = resourceType("room");
const room1 = resource(room,
[timeslotFns.sameDay("2023-07-01", "09:00", "17:00")], [],
resourceId("room1"));
const room2 = resource(room,
[timeslotFns.sameDay("2023-07-01", "09:00", "17:00")], [],
resourceId("room2"));
const anySuitableRoom = anySuitableResource(room);
const meetingService = service(
resourceRequirements([anySuitableRoom]));
const requestedBooking = bookingSpec(meetingService,
[resourceCommitment(anySuitableRoom, room2)]);
const requestedTimeSlots = [
timeslotFns.sameDay("2023-07-01", "10:00", "11:00"),
timeslotFns.sameDay("2023-07-01", "11:00", "12:00"),
timeslotFns.sameDay("2023-07-01", "13:00", "14:00"),
];
const availability = listAvailability(
[room1, room2],
[],
requestedBooking,
requestedTimeSlots
)
availability.forEach((slot) => {
const time = `${startTime(slot)} to ${endTime(slot)}`
if (slot._type === "available") {
console.log(`Slot ${time} is available`);
console.log(`\tIt uses resource : ${(bookedResources(slot))}`);
console.log(`\tThe potential capacity at this slot is ${slot.potentialCapacity.value}`)
console.log(`\tThe consumed capacity at this slot is ${slot.consumedCapacity.value}`)
} else {
console.log(`Slot ${time} is unavailable`);
}
});
And in the resulting output, you can see that all the slots end up using room2
everywhere:
Slot 10:00 to 11:00 is available
It uses resource : room2
The potential capacity at this slot is 2
The consumed capacity at this slot is 0
Slot 11:00 to 12:00 is available
It uses resource : room2
The potential capacity at this slot is 2
The consumed capacity at this slot is 0
Slot 13:00 to 14:00 is available
It uses resource : room2
The potential capacity at this slot is 2
The consumed capacity at this slot is 0
Choosing resources based on attributes
This final piece of code shows how you can check availability against resources that have attributes - the typical meeting room resourcing case.
const room = resourceType("room");
const room1 = resource(room,
[timeslotFns.sameDay("2023-07-01", "09:00", "17:00")], [
{name: "capacity", value: 10},
{name: "hasProjector", value: true}
], resourceId("room1"));
const room2 = resource(room,
[timeslotFns.sameDay("2023-07-01", "09:00", "17:00")], [
{name: "capacity", value: 20},
{name: "hasProjector", value: true}
], resourceId("room2"));
const meetingRoomRequirement = complexResourceRequirement(room,
[
{name: "capacity", value: 15, operator: "greaterThan"},
{name: "hasProjector", value: true, operator: "equals"}
]);
const meetingService = service(
resourceRequirements([meetingRoomRequirement]));
const proposedBooking = bookingSpec(meetingService);
const requestedTimeSlots = [
timeslotFns.sameDay("2023-07-01", "10:00", "11:00"),
timeslotFns.sameDay("2023-07-01", "11:00", "12:00"),
timeslotFns.sameDay("2023-07-01", "13:00", "14:00"),
];
const availability = listAvailability(
[room1, room2],
[],
proposedBooking,
requestedTimeSlots
);
availability.forEach((slot) => {
const time = `${startTime(slot)} to ${endTime(slot)}`
if (slot._type === "available") {
console.log(`Slot ${time} is available`);
console.log(`\tIt uses resource : ${(bookedResources(slot))}`);
console.log(`\tThe potential capacity at this slot is ${slot.potentialCapacity.value}`)
console.log(`\tThe consumed capacity at this slot is ${slot.consumedCapacity.value}`)
} else {
console.log(`Slot ${time} is unavailable`);
}
});
Here we assign attributes to the resources and express a need against these attributes using complexResourceRequirement
. We have two rooms, both with a projector, but one has capacity 10 and the other capacity 20.
We request a projector and a capacity of 15 or more, so the only match is room2
, and indeed the resulting output is:
Slot 10:00 to 11:00 is available
It uses resource : room2
The potential capacity at this slot is 1
The consumed capacity at this slot is 0
Slot 11:00 to 12:00 is available
It uses resource : room2
The potential capacity at this slot is 1
The consumed capacity at this slot is 0
Slot 13:00 to 14:00 is available
It uses resource : room2
The potential capacity at this slot is 1
The consumed capacity at this slot is 0
There is a ton of stuff glossed over here, not least:
that resources have their own availability
that
capacity
based services are possible (think a yoga class taking in 12 people)that complex resource requirement combinations are supported
Regardless, I hope you get a flavour of what's possible using the breezbook resourcing and availability functions.
The repo is here and these specific test cases are available here.
Subscribe to my newsletter
Read articles from Mike Hogan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Mike Hogan
Mike Hogan
Building an open source booking and appointments software stack - https://github.com/cozemble/breezbook