Basic workflow for a touristic website:
Which webservices do we need for the basic workflow?
There are a total of 18 different webservices, but it is not necessary to use all of them. The bare minimum to create a complete vacational rentals website are:
Catalog
DailyAvailability
DailyRates
Lodging
Calendar
Homepage:
We create a search bar with 3 inputs: arrival_date, departure_date and people.
The button “Search availability” will link to a new page with the parameters for the inputs, where we will show the list of available properties.
List of properties:
We read the parameters of the URL.
Option 1: If the parameters exist → we will show the available properties for those dates / people, with the total price of the stay.
Option 2: If there are no parameters → we will show all the properties in the system that have the minimum requirements. We can show the minimum price, so that the user has an idea, but it’s optional.
Option 1: Show available properties:
First, we call DailyAvailability()
DailyAvailability(“2022-01-01”, “2022-01-05”, 3, “en”, “test_user”, “test_psw”)
This will return the list of available properties in those dates, with all the information except prices.
Then, we call DailyRates() for each one in a recursive function.
DailyRates(1011, “2022-01-01”, “2022-01-05”, 3, “en”, “test_user”, “test_psw”)
This will return de prices for that property and dates.
Field in screenshoot | Webservice | Field in webservice |
---|---|---|
1. Title | DailyAvailability | headline / name |
2. Description | DailyAvailability | description |
3. Photo | ||
4.1 Capacity | DailyAvailability | maximum_capacity |
4.2 Bedrooms | DailyAvailability | number_of_rooms |
4.3 Surface | DailyAvailability | surface |
4.4 Wifi | DailyAvailability | lodging_equipment.wifi / lodging_equipment.free_wifi |
5. Price of stay | DailyRates | price |
Other important fields from DailyAvailability and DailyRates:
Webservice | Field | Description |
---|---|---|
DailyAvailability | lodging_id | You must read this to access the DailyRates function |
DailyAvailability | lodging_type | Useful to filter by apartment / villa |
DailyAvailability | city | Useful to filter by destination |
DailyAvailability | latitude & longitude | Necessary if you want to create a Google Maps |
DailyAvailability | release | Necessary if the properties have different release ** |
DailyAvailability | rating & review | Useful if you want to put the stars + reviews here |
DailyRates | closed_to_arrival | If closed_to_arrival=true, that property can’t be booked with the arrival_date, even if it’s available. You should put a message informing the user. |
DailyRates | closed_to_departure | If closed_to_departure=true, that property can’t be booked with the departure_date, even if it’s available. You should put a message informing the user. |
DailyRates | minimum_stay | If search nights < minimum_stay, the reservation can’t be made for that number of nights. You should put a message informing the user. |
** What is the release?
It’s the number of days from today to the first possible check-in date.
For example:
Today is 16/09/2021.
I have an apartment available, but it has release=1.
This means that I can’t make a reservation with check-in 16/09/2021. The apartment will be available for check-in 17/09/2021 onwards.
The most normal values for release are 0 (accepts check-ins for today) or 1 (accepts check-ins starting tomorrow), but there can be others.
When should we read this value?
If the Property Manager uses the same release for all the catalogue (let’s say release=1), the easiest way to deal with this is to put this restriction directly in the calendar datepicker.
If the user can’t pick today in the calendar, then they can’t make a reservation for today.
But, if the Property Manager has different release values for each property, then we can’t use this solution.
In this case, we must read the “release” value in DailyAvailability.
If the arrival_date is 16/09/2021, and today is 16/09/2021, and the property has release=1, then we show a message with something like:
“This apartment is not available for a check-in. Contact us to ask more information.”
or we don’t show the property at all, since it can’t be booked.
This is up to the developer and the client.
Option 2: Show all properties:
We call Catalog()
Catalog("", 0, "en", "test_usr", "test_pwd")
The parameters will be almost the same that when doing a search.
The only thing that changes is the price. We will not show the price of the stay, because we don’t have dates and thus we can’t calculate the prices for a specific interval of dates.
What we can show is the minimum price of the year for that property.
Catalog.minimum_rate → this will give us the minimum price, then we can put something like:
Property page:
COMING SOON
For the property page we will use Lodging, Calendar and DailyRates.
This is a page with the minimum content:
Availability in the search calendar of a property:
In the property page there is a calendar to search for available dates to book.
Ideally, we want this calendar to show only the available dates for that property so that the user can’t search unavailable dates. This will make the interaction more user friendly:
There is a tricky part in this routine, because for the departure/checkout calendar we need some unavailable dates to be clicked:
In this example, if we want to book from 11th to 14th of March, the nights that we are booking are the 11th, 12th and 13th, BUT we need to be able to click the 14th as a checkout date, even if it’s not available for the night.
So, how can we develop this routine so that the calendar shows us the available/unavailable dates in the “arrival date” option, but only the dates that we can do the checkout in the “departure date” option?
We use the Datepicker jQuery library, that you can find here: https://jqueryui.com/datepicker/
In the jQuery code we have added a few functions to read the arrays with the availability that we have previously created.
The Datepicker routine will have these following custom variables:
nonAvailableCheckin array → array previously created with the available dates for check-in
nonAvailableCheckout array → array previously created with the available dates for check-out
#checkinDate → the ID from the input in the HTML for the arrival date
#checkoutDate → the ID from the input in the HTML for the departure date
{clickedDate} → the date that the user selects
{minDate} → the first date that can be selected. By default it will be “today”, but if you are working with release dates, this can change
{minimumStay} → the minimum stay for those specific interval of dates. Sometimes it is interactive and sometimes it is a static value
The Datepicker routine will look like this:
<script> $(function () { $.datepicker.regional['en'] = { dateFormat: 'dd/mm/yy', minDate: 0, firstDay: 1, isRTL: false, beforeShowDay: function(date) { let nonAvailable = jQuery.datepicker.formatDate('dd/mm/yy', date); return [ nonAvailableCheckin.indexOf(nonAvailable) == -1 ] } }; $.datepicker.setDefaults($.datepicker.regional['en']); }); $('#checkinDate').datepicker({ setDate: '{clickedDate}', minDate: '{minDate}', onSelect: function (selected) { let date = $(this).datepicker('getDate'); if (date) { date.setDate(date.getDate() + {minimumStay}); } $('#checkoutDate').datepicker('option', 'minDate', date); let today = new Date(); let diffToday = 0; for (let x = 0; x < nonAvailableCheckout.length; x++) { let parts = nonAvailableCheckout[x].split('/'); let mydate = new Date(parts[2], parts[1] - 1, parts[0]); if (mydate > date) { $('#checkoutDate').datepicker('option', 'maxDate', mydate); break; } } } }); $('#checkoutDate').datepicker({ setDate: '{clickedDate}', minDate: '{minDate}', beforeShowDay: function(date) { let nonAvailable = jQuery.datepicker.formatDate('dd/mm/yy', date); return [ nonAvailableCheckout.indexOf(nonAvailable) == -1 ]; } }); </script>
nonAvailableCheckin and nonAvailableCheckout array:
Dim property_id As Integer = 1001 'Variables needed for the logic: Dim arrivalDaysNotAvailable As String = "" Dim departureDaysNotAvailable As String = "" Dim minimumStays As String = "" Dim dayBeforeAvailable As Boolean = False 'Reading the Calendar WS for the next 12 months 'Here we will create 2 arrays, one for arrivals and one for departures, where we will put all the unavailable dates: Dim cson As String = icnea.Calendar(property_id, Today, 12, Funcions.Empresa, Funcions.Password) Dim css As Object = New JavaScriptSerializer() With {.MaxJsonLength = Int32.MaxValue} Dim c As Object = css.Deserialize(Of Object)(cson) If c("Calendar").length > 0 Then For i As Integer = 0 To c("Calendar").length - 1 If CBool(c("Calendar")(i)("available")) Then 'available days dayBeforeAvailable = True Else If dayBeforeAvailable Then 'it is the first unavailable day of the interval Else 'unavailable days for the departure calendar departureDaysNotAvailable &= """" & CDate(c("Calendar")(i)("date")).ToString("dd/MM/yyy").Replace(".", "/").Replace("-", "/") & """," End If 'unavailable days for the arrival calendar arrivalDaysNotAvailable &= """" & CDate(c("Calendar")(i)("date")).ToString("dd/MM/yyy").Replace(".", "/").Replace("-", "/") & """," dayBeforeAvailable = False End If 'minimum stay minimumStays += c("Calendar")(i)("minimum_stay") & "," Next End If 'We delete the last character for each array, which is a comma If arrivalDaysNotAvailable.Length > 0 Then arrivalDaysNotAvailable = arrivalDaysNotAvailable.Remove(arrivalDaysNotAvailable.Length - 1) End If If departureDaysNotAvailable.Length > 0 Then departureDaysNotAvailable = departureDaysNotAvailable.Remove(departureDaysNotAvailable.Length - 1) End If If minimumStays.Length > 0 Then minimumStays = minimumStays.Remove(minimumStays.Length - 1) End If 'We add the arrays in this variable that will be the script that we will add before the Datepicker routine: Dim datePickerArrays As String = "" datePickerArrays &= "<script>" datePickerArrays &= "let nonAvailableCheckin = [" & arrivalDaysNotAvailable & "];" datePickerArrays &= "let nonAvailableCheckout = [" & departureDaysNotAvailable & "];" datePickerArrays &= "let minimumStay = [" & minimumStays & "];" datePickerArrays &= "</script>"
Add Comment