In the first post of this series, we created the page showing all the hotel room’s information. It normally has a button or several call-to-action areas to go to the booking page which allows your customers to make an order. However, ‘cause some businesses have strong direct channels, they want their sales to make booking orders for their customers as well. Along with that, to have you imagine how to create a booking page in the frontend later (which is in the 3rd post), I made this post to show you how to create one in the backend. That is for internal users only.

The necessary plugins were mentioned in the first post of this series, just follow it.

Now, let’s get started!

Create a New Custom Post Type

We are going to create a new custom post type named Booking. Each created booking order will be a post in this post type.

Head to Meta Box > Post Types > New Post Type in the admin dashboard to create a new custom post type.

Fill in the information for the post type, in there:

  • Name of the post type: Booking;
  • Supports: unchoose default fields and just tick the Revision to allow tracking changes;
  • Menu position after: choose a position in the admin menu to display the post type.
Create a new custom post type named Booking
Create a new custom post type named Booking

Next, you can press Publish to save the post type then go to Meta Box > Custom Fields > Add New, or just press the below Add Custom Fields button for the next steps.

Press the Add Custom Fields button to create custom fields for the Booking post type
Press the Add Custom Fields button to create custom fields for the Booking post type

Create Custom Fields for the created “Booking” post type

For the booking page, we need to create a bunch of different fields. You should clarify in advance what you want, how users fill in the data, how to show fields and their value, etc. That’s will make the process to create them easier. As my supposition, all the fields I need are as following:

Name Field type Function
Order Number number Is an array of numbers and auto-generated whenever the booking is created
Booking Date date Date of creating the booking
Person in Charge user Choose one from the list of users in WordPress
Customer information heading Separate the sections
·  Full Name text
·  Mobile number
·  Email email
·  Address text
·  Notes textarea
Booking Information heading Separate the sections
Booking Details group Group of fields regarding the booking room. This group is cloneable for the case that the customer books multiple rooms
· Room post Choose one from the list of the rooms
· Price number
· Adults number
· Children number
· Age of Children (1, 2) number Each field is for a child. This field is auto-display whenever there is one more child
· Extra Bed number
· Check-in Date date
· Check-out Date date
· Total Nights of Stay number Auto-calculated bases on the check-in and check-out date
Total Number of Rooms number Auto-calculated bases on the number of the group about the room details
Other Request textarea
Payment Information heading Separate the sections
·  Total Amount number Auto-calculated bases on room details and number of rooms
·  Paid Amount number Manual input by sales
·  Unpaid Amount number = Total amount – paid amount
Booking Status heading Separate the sections
·  Booking Status select Choose one from the provided statuses
·  Refund (if any) select Choose one level (%)  from the provided levels

We’ll create some of the prominent fields because there are quite many fields here and although they are different field types but have the same way to create.

I’m using Meta Box Builder so the execution will be visual and easier. In case you are not, you must create each field by code.

Create a Field Group

Before creating any field, we need to create a field group (means custom meta box) to contain all the fields.

As I said above, you may go to Meta Box > Custom Fields > Add New in your admin dashboard, or press Add custom fields in the edit page of the Booking post type.

press Add custom fields in the edit page of the Booking post type

In the Settings tab of the Edit Field Group screen, choose Booking in the Post Types section.

Allows the Field Group display in the post type is Booking
Allows the Field Group display in the post type is Booking

Next, come back to the Fields tab in the Edit Field Group screen to create one by one custom field as you need.

Create a Number Field for Order Number

In the Fields tab of the Edit Field Group screen, choose Number in the Basic section in the left column. A Number field will appear.

Because the Order Number field is auto-generated information that users can not input or edit, I ticked to the Ready Only and Disable boxes.

Create a number field for the Order Number
Create a number field for the Order Number

Create a field for Person in Charge

Sales, who are the persons in charge of the booking orders, have their own admin account in WordPress. So, we create a field that shows all the usernames in WordPress to pick one from them.

In the left bar, just choose User in the WordPress section.

Create a user field
Create a user field

Create a heading to separate the sections

Heading actually is a field in the type of Layout. It is different from others that it has no ID and does not allow users to input any data as well. It just displays as a heading to separate the sections or groups so that the form will look more well-structured.

Create a heading to make the form look better
Create a heading to make the form look better

Create a Group of Fields for Booking Details

This group includes all the fields about the room, price, adults, children, age of children, extra bed, check-in & check-out date. To group them all, we need help from the Meta Box Group.

In the Layout section, choose Group:

Create a Group of Fields for Booking Details

In this group, I set Custom CSS Class to track the event when the user clones the group. This will help to calculate the total room later.

Create Custom CSS Class for a group
Create Custom CSS Class for a group

Besides that, each sub-field in this group has some remarks:

1. Fields for the Room Name:

I choose the field type is Post for this field and show all the posts which are in the Room post type (rooms we created in the first post of this series).

Fields for the Room Name

2. The Children field:

As the regulation of each hotel, children may be charged or not depend on their ages. So we will create additional fields to fill in their ages. An additional field for age will appear when you add one more in the Children field. I restrict the maximum number of children is two as well.

I use Meta Box Conditional Logic to set a condition for the age fields.

Limit the maximum number of children
Limit the maximum number of children
Set a condition to decide when the age field displays
Set a condition to decide when the age field displays

Like the above image, I set the Age of Children 1 field displays when Children >=1. It is likewise for the Age of Children 2, displays when Children >=2.

3. Check-in Date and Check-out Date:

We create these fields in the type of normal date with a calendar. In the last post of this series, we will show the vacant room to the calendar in realtime.

In the Advanced section, choose Date. This field will show a calendar to choose a date instead of typing.

Create a field for check-in date and check-out date fields
Create a field for check-in date and check-out date fields

Create Custom Fields for Others

It is likewise to create other custom fields.

Regarding the price and payment fields, just create it. We will tackle them in the next step to make it be auto-calculated.

When you finish creating the custom fields, the form of the booking order will be like this:

Booking order in the backend
Booking order in the backend

Add Extra Functions to the Custom Fields

In this step, we are going to deal with some special fields to automatically calculate or generate value for them. In details:

  • Automatically generate booking order number;
  • Automatically calculate the total number of booking rooms;
  • Automatically display the corresponding price of the booking room;
  • Automatically calculate the total nights of stay;
  • Automatically calculate the total amount.

We’ll need to code much in this part. Let’s go!

Automatically Generate Booking Order Number

Each post in the Booking post type has neither title nor the permalink. All of them will be kinds of the Auto Draft after saving. So, we will get the post ID and set it to be the title and permalink as well.

This is the post before we create a title for it:

Add Extra Functions to the Custom Fields

Now, add these codes to the functions.php in the theme folder:

function update_post( $post_id ) {
   $post = array(
     'ID'         => $post_id,
     'post_title' => '#'.$post_id,
     'post_name'  => $post_id,
   );
   wp_update_post( $post );
   update_post_meta($post_id, 'order', $post_id);
}
add_action('save_post_booking', 'update_post', 20);

In there, update_post_meta($post_id, 'order', $post_id) helps to set the post ID to be the value of the Order Number field.

Save the functions.php file, then create a new booking order for a try. You’ll see the title of order as below:

Post ID is set to be title and permalink of the order
Post ID is set to be title and permalink of the order
The order number is auto-generated by post ID
The order number is auto-generated by post ID

Automatically Calculate the Total Number of Booking Rooms

The quantity of room will be 1 in default, equivalent to 1 group of booking details for 1 room. Whenever users press Add More or Add Room, we will add one more unit to this field.

We will solve this by javascript in the backend. So, add these codes to the functions.php file. It is used to register a file that has the link is /js/booking.js to post-page.php of the Booking post type.

function add_admin_scripts( $hook ) {
   global $post;
   if ( $hook == 'post-new.php' && 'booking' === $post->post_type) {
   wp_enqueue_script( 'booking-js', get_stylesheet_directory_uri().'/js/booking.js' );
   }
}
add_action( 'admin_enqueue_scripts', 'add_admin_scripts' );

Next, create a file named booking.js in the js folder.

create a file named booking.js in the js folder.

Open it and paste these codes there:

jQuery( document ).ready( function( $ ) {
   $('.group-bookings .add-clone').on('click', function(e){
      setTimeout(function(){
        var rooms = $('.group-bookings .rwmb-group-clone').length;
        $('input#amount').val(rooms);
        update_js();
      }, 100);
   });

   function update_js(){
      $('.group-bookings .remove-clone').on('click', function(e){
         setTimeout(function(){
           var rooms = $('.group-bookings .rwmb-group-clone').length;
           $('input#amount').val(rooms);
         }, 100);
      });
   }
});

This js code helps us to update the quantity of room whenever users press the Add Room or Remove buttons.

In there:

  • ‘group-booking’: is the Custom CSS Class of the group of fields about booking details;
  • ‘amount’: is the ID of the Total Number of Room field;
  • Add-clone, remove-clone: is the Custom CSS Class of the Add Room or Remove button. To see this information, you may press F12:
View the custom CSS class of two buttons
View the custom CSS class of two buttons

Automatically Display the Corresponding Price of the Booking Room

First, we set the field Price is Read only with a condition to display is that the value of the Room field is not “empty”. It means that when the Room field has any value (not leave it blank), the Price field will appear.

Automatically Display the Corresponding Price of the Booking Room

Next, I will create a global variable in js. This variable will be an array contains all the information about the price and ID of the rooms. Whenever users choose a room, this variable will be checked. If the ID of the booking room matches an ID in the array, the corresponding price will be shown.

To create this variable, open the functions.php file and replace the code registering the booking.js file by these ones:

function add_admin_scripts( $hook ) {
    global $post;
    if ( $hook == 'post-new.php' || $hook == 'post.php' ) {
        if ( 'booking' === $post->post_type ) {
            wp_register_script( 'booking-js', get_stylesheet_directory_uri().'/js/booking.js' );
            $rooms = get_posts(array(
                'post_type' => 'room',
                'posts_per_page'=> -1
            ));
            $arr_rooms = array();
            foreach ($rooms as $room) {
            array_push($arr_rooms, array('id'=>$room->ID, 'price'=>rwmb_get_value('price','', $room->ID)));
            }
            wp_localize_script( 'booking-js', 'rooms_data', $arr_rooms);
            wp_enqueue_script( 'booking-js' );
        }
    }
}
add_action( 'admin_enqueue_scripts', 'add_admin_scripts', 10, 1 );

Then paste these codes to booking.js:

$( ".group-bookings .rwmb-field select[name*='[room]']" ).on('change', function(){
    var curr = $(this).val();
    var price_unit = $(this).closest('.rwmb-field').siblings().find("input[name*='[price_unit]']");
        rooms_data.forEach(function(val, i){
            if (curr == val['id']){
                price_unit.val(parseInt(val['price']));
            }
        });
});

The price will be auto-displayed now:

The Auto-displayed Price

Automatically Calculate the Total Nights of Stay

Before calculate the total nights of stay, we should set a condition that the check-out date must be after the check-in date. I use js to set the minDate of the check-out date is the check-in date plus one unit.

Paste these code to the booking.js file:

$( ".group-bookings .rwmb-field input[name*='[check_in]']" ).on('change', function(){
         var d = new Date($(this).val());
         var af_date = d.getDate() + 1;
         var af_month = d.getMonth() + 1;
         var af_year = d.getFullYear();
         var min_date = af_year + '-' + af_month + '-' + af_date;
$(this).closest('.rwmb-field').siblings().find("input[name*='[check_out]']").datepicker('option', 'minDate', min_date);
});

Now, to automatically count the number of booking nights, add these code to the booking.js file:

$( ".group-bookings .rwmb-field input[name*='[check_out]']" ).on('change', function(){
var total = calculate_total_day($(this).closest('.rwmb-field').siblings().find("input[name*='[check_in]']").val(), $(this).val());
$(this).closest('.rwmb-field').siblings().find("input[name*='[total_nights_stay]']").val(total);
});
function calculate_total_day(check_in, check_out){
    var date1 = new Date(check_in);
    var date2 = new Date(check_out);
    return (date2.getTime() - date1.getTime()) / (1000 * 3600 * 24);
}

From now on, your Total Nights of Stay field’s value is automatically-changed when you choose a date:

Automatically calculate the total nights of stay
Automatically calculate the total nights of stay

Automatically Calculate the Total Amount

Formula to calculate the total amount as below:

Total Amount = (Price of room 1 + numbers of extra bed in room 1 * price) * nights
                      + (Price of room 2 + numbers of extra bed in room 2 * price) * nights
                      + …
                      + (Price of room N + numbers of extra bed in room N * price) * nights

In there, I set the Extra Bed is a kind of room and has a fixed price. At the same time, I create a field for the Total Amount of Each Room:

Total Amount of Each Room = (Price of room + numbers of extra bed * price) * nights

We just need to summarize all the Total Amount of Each Room to get the Total Amount of the booking.

Add these code to the booking.js file to calculate the total amount of each room:

$( ".group-bookings .rwmb-field input[name*='[check_out]']" ).on('change', function(){
var total = $(this).closest('.rwmb-field').siblings().find("input[name*='[total_nights_stay]']").val();
        var price_unit = $(this).closest('.rwmb-field').siblings().find("input[name*='[price_unit]']").val();
        var extra = $(this).closest('.rwmb-field').siblings().find("input[name*='[extra_bed]']").val();
        rooms_data.forEach(function(val, i){
            if (498 == val['id']){
                total_extra = extra*parseInt(val['price']);
            }
        });
$(this).closest('.rwmb-field').siblings().find("input[name*='[total_amount]']").val((parseInt(price_unit)+parseInt(total_extra))*total);
});

And also add this one to calculate the Total Amount (Grand Total):

function update_total_payment(){
        var total_payment = 0;
        $( ".group-bookings .rwmb-field input[name*='[total_amount]']" ).each(function(){
             total_payment = parseInt(total_payment) + parseInt($(this).val());
        })
        $('#total').val(total_payment);
    }

Now, all the fields will automatically run as your logic:

Total Amount (Grand Total) run automatically

For your quick reference, this is my booking.js file:

Final Words

In this tutorial, I assumed all about the logic and process of booking. So, you should adjust the fields and functions to meet your using in reality. We will create a booking order form in the frontend as well as show the vacant rooms in the calendar in the next posts. Keep an eye on our next blog posts!

Leave a Reply