A resource is any item or service that can be reserved in the context of an event. Strictly, a resource is actually a type, or class, of resource. The base resource type is the session. Other typical resource types are meals and accommodation.
Each resource type have resource instances, such as rooms for the accommodation. Each resource instance can have characteristics that limit their reservation, such as capacity limit and quantity. For example the resource type "accommodation" can have the instances, or rooms, "single room" and "double room". The capacities will be, respectively, 1 and 2. If the quantities are, for example, 4 and 3, the total capacity is 4 places in single-room and 6 places in double-room. The age and gender can also be taken into account to restrict the booking. A resource can also be offered with alternative sets of capacity limits. For instance a room can be offered as both a single-room and a double-room, whichever configuration gets booked first defines the actual capacity of that particular resource instance. Overbooking can also be defined as an internal management instrument so that the real occupation is reflected in the system.
In the DREAM booking system, resources are not fixed static entities. Resources are abstract and DREAM don't diferentiate them.
An event is a bookable set of resources. Masterclasses, day courses, retreats and festivals are examples of events.
An event usually takes place in consecutive days (longer events can have free days). Each event can have its own set of resources available for booking. Which means that resources can be freely defined for each event. For instance an event could organize transportation and have that resource offered for booking.
The bookable resources are mainly the sessions, but can also include meals, accommodations and others. Sessions can be offered in any granularity such as individual teachings or guided meditations, or individual days of the event. This choice just depends on the most adequate granularity to support the booking combinations that will be offered. For example a multi-day event that hás an empowerment day can be offered in two forms, "full event" and "empowerment day". The best granularity in this case might be daily sessions because it's the minimum time that can be booked. Then the "full event" will be associated with a session per day while the "empowerment day" will be associated with the sessions of that same day. In another examples the minimum bookable session is each teaching or guided meditation, só in that case the booking form can offer possibilities such as booking for mornings and/or afternoons of each day. The same approach can be applied to the meals, accommodations or other resources. The granularity choice of a resource, such as sessions, is independent of the granularity of others resource types. So while the sessions can represent individual teachings or periods of the day, the accommodations can be booked only for full days or for the whole period.
Events are characterised by:
The beginning and end dates are self-explanatory. The type is restricted to a pre-defined list that can be changed or increased at any time. The name is a short tag that whenever possible should be equal to the type. It's used to create a unique identifier for the event together with the begin date. Examples of types and names are: class, meditation, festival and retreat. The best names (or types) are short single words, because they will be used both in the URLs provided for the booking and for file storage (where directories in the file system will also use those names).
URLs for the booking form of events are generated automatically and are in the form of https://dream.kadampa.pt/event/year/month/day/name/index.html This year/month/day is the date when it begins. This date coincides with the date for the first bookable resource. The name can use any language available on a computer (depending on the underlying operating system, it may be best to avoid non-ASCII characters).
In general, an activity is a set of one, or more, events.
A set of wednesday classes (events) can be bundled together in a single activity and offered as an activity. An example is a course with 3 classes on the general topic of love where each class (event) focus in one type of love. The set of events can be booked in a bundle through an activity. Each event can take place in a different date or have different names and types. More events can always be added to an activity.
The benefit of activities is twofold. In one hand, they simplify the booking form and, on the other, enable special discounts for event bundles. An event can be part of multiple activities, so it's possible to create many bundles, each one with it's own booking form, prices and rules. The challenge might only be the price and rules consistency across several bundles that include common events..
The booking form for an activity can offer options that apply equally to all events, or if required, it can offer all the specific options per event, like filling a booking form per event without the extra effort of repeating the personal details.
Activities (like events) are characterised by:
The beginning date of an activity coincides with the beginning date of the first event. In the same way, the ending date of an activity coincides with the ending date of the last event. The name of an activity is independent of the names of its events. The naming is restricted to a pre-defined list that can be changed or increased at any time. An example of a name is "course". In this case a good name for each of its events can be "class".
The URL for the booking form of any activity has the same format and rules as the event URLs. The only difference is that "event" is replaced by "activity" so its form will be https://dream.kadampa.pt/activity/year/month/day/name/index.html
A booking is a reservation of resources for periods of an event or activity by a person.
Bookings can be set to open and close at specific dates and times. Bookings can also be open or closed for temporary maintenance.
An example of this configuration is:
"booking": {
"create": [
{
"date": {
"begin": "2025-03-20",
"end": "2025-09-26 23:00"
},
"open": true
}
]
}
In reality what is offered for booking are the resource instances. For example the resource "session" can offer the instances "local" and "remote". They function as different rooms, or spaces, for the sessions. The space reservation of a resource instance corresponds to reserve a seat at the session venue or a seat at the dining marquee. So this booking dimension is called "space". Resources can be offered with different "space" presentations, each one with its own characteristics and restrictions. Each resource presentation can also be set to open and close at specific dates and times and also have its own open/close control. A resource presentation includes a capacity, and possibly, a quantity and an overbooking margin.
An example of the configuration of a "space" for meals is:
"s_Meal": [
{
"value": "vegetarian",
"rooms": [ "cafe" ],
"capacity": 17,
"quantity": 1,
"overbooking": 0
}
]
The availability of resources can also be time-limited, that is a resource, or resource configuration, is only available until a certain date, or only after a certain date. Every resource also offers a "open" (available) or "closed" (unavailable) control to allow removing it from booking.
An example of this configuration is:
"s_Accommodation": [
{
"value": "camping",
"rooms": [ "camping" ],
"capacity": 1,
"overbooking": 0,
"quantity": 5,
"date": {
"end": "2025-09-15"
},
"open": true
}
]
Some resource presentations can limit the resources on offer depending on previous options, such as the age and gender for the accommodations.
"s_Accommodation": [
{
"value": "dormitory",
"rooms": [ "quadM1", "quadM2" ],
"capacity": 4,
"overbooking": 0,
"AND": [
{"gender": "male" },
{"age": "adult" }
]
}
]
Booking associates this "space" dimension to a "time" dimension. With a booking the person is actually choosing the period(s) of time when each resource will be reserved to him/her.
A third, and final, dimension is "quantity". A person can reserve multiple instances of a resource for specific periods. For example a person can book a full double-room. This does not mean that the booking form has to offer this possibility. It only means that a booking form can offer it.
Associated with the booking of a resource instance is usualy a price, set of discounts and deposit. Each of these fields can have not only periods when they apply but also modifiers depending of previous booking options. An example is the price, or discount, for sessions that depends on the age group. Another example is an "early bird" discount until a certain date.
An example of this configuration is:
"t_Session": {
"full": {
"price": [
{
"amount": 45
}
],
"discount": [
{
"IF": { "age": "infant"},
"percentage": 90
},
{
"IF": { "age": "child" },
"percentage": 50
}
],
"deposit": [
{
"IF": { "age": "infant"},
"percentage": 90
},
{
"IF": { "age": "child" },
"percentage": 60
},
{
"IF": { "age": "adult" },
"percentage": 25
}
]
}
}
The life cycle of a booking has 5 stages: candidate, accepted, confirmed, completed and deleted.
A booking enters the candidate state when it's submited from a booking form. In this stage the validation is done client-side (javascript running in the browser). Because the booking is probably ready to be accepted it's stored in the server as a candidate booking and the client receives a short token that identifies this booking stage and serves as confirmation of the preliminary acceptance. The client (javascript) then requests the acceptance of the booking which triggers the server-side validation. If this validation is not successful, the person can review its booking options, update its candidate booking and request again the acceptance of the booking. If the validation is successful the booking advances to the accepted state and gets a number. The client receives this number which confirms the acceptance of the booking. Also an email is sent to the person with the booking data.
The two-stage process of candidate and accepted has a couple of benefits. In one hand, a probable valid (client-side verification only) booking is stored but doesn't enter immediately the regular (accepted) bookings list without proper (server-side) validation. Even though the client has all the data to control which resources can be booked, a booking could come from a malfunctioning or altered client. So the server-side validation is mandatory. One advantage of storing the candidate booking comes from the speed of feedback from the server regarding the submission. The client already receives an identifier (token) that shows the booking has been saved while it remains waiting for the final acceptance. From the point-of-view of the system it allows further investigation in case candidate bookings don't proceed to the accepted state. Because the booking data is already on the side of the server, if some error occurs in the server-side validation it can be corrected and the candidate bookings can be recovered and mass accepted in the same order that they entered the server. While errors in client-side validation are easy to test (with the booking form UI), errors in the server-side validation are more difficult to test (without a specialized UI). Another advantage of this approach is that non-server-side validated bookings don't enter the regular list and also don't reserve a booking number, which helps keeping the booking list cleaner and avoids reserving booking numbers for anomalous or edge bookings. These are bookings that were correctly validated in the client but while on its way to server-side validation became invalid due to an unavailable resource. This probably occurred because another booking was happening at the same time, and was server-side validated first, so it reserved the requested resources, and at least one of them became unavailable. When the client receives the information that the booking was not accepted it refreshes its data for resource availability and allows the person to continue the booking by selecting other (available) options. The submission of revised form data, together with the received token, only triggers an update to the candidate booking.
An accepted booking can be changed or deleted. Each change is logged which allows to recover any previous data state of a booking. Deleting a booking only removes it from the active bookings list, so it's always possible to revert that action.
The confirmed and completed states are related to payment.
An accepted booking where the deposit was paid is in the confirmed stated. An accepted booking without a remaining balance (amount left to be paid) is in the completed state.
Bookings for an event, or activity, can be packed to facilitate the management and payment procedures for groups of persons, such as families, that attend together events. Another purpose of packs is to allow special discounts for groups, such as families. This structure is as follows:
"pack": {
"calculator": {
"age": {
"discount": [
{
"IF": { "age": "adult" },
"nbookings" : 3,
"ormore": true,
"amount": 7.5
},
{
"IF": { "age": "adult" },
"nbookings" : 2,
"amount": 6
}
]
}
}
}
A (booking) pack is not a shopping cart. It's only a collection of bookings for the same event/activity. While a shopping cart requires some personal details (like name, email or address) once, in a pack each booking will have to provide its own specific personal details.
Each individual submited booking has its own pack, which means that, at any time, new bookings can be added to it.
Any person of the booking pack receives access to the state of bookings and payments for that pack, and can complete any pending payments. Payments are attributed to the bookings in the pack following their order in the list (date of submission). So any payment is attributed to the first booking in the pack that has remaining balance. Because of this, it's possible that some persons of a pack have their bookings confirmed, or completed, while others are still in progress (accepted but not yet confirmed or completed).
A portal is a special form that offers alternative activities for booking. For example, the form can ask if the person wishes to book for the whole activity or for single events. After this it loads the respective booking forms.
A shopping cart can have multiple unrelated packs. It simplifies both the persons looking to book events, by just requiring once the personal details, and the management that can offer special discounts on booking multiple activities without the need to create a new activity just for that sake.