diff --git a/appointment/DvgAppointment.inc b/appointment/DvgAppointment.inc
index f2ce736..1401c86 100644
--- a/appointment/DvgAppointment.inc
+++ b/appointment/DvgAppointment.inc
@@ -30,6 +30,13 @@ class DvgAppointment {
   private $end;
 
   /**
+   * Location.
+   *
+   * @var int
+   */
+  private $location;
+
+  /**
    * A list of products.
    *
    * @var array
@@ -75,6 +82,23 @@ class DvgAppointment {
     $this->end = $end;
   }
 
+  /**
+   * Sets the location.
+   *
+   * @param int $location
+   */
+  public function setLocation($location) {
+    $this->location = $location;
+  }
+
+  /**
+   * Get the appointment location.
+   *
+   * @return int $location
+   */
+  public function getLocation() {
+    return $this->location;
+  }
 
   /**
    * Gets the local appointment id.
diff --git a/clients/gplan.inc b/clients/gplan.inc
index 37c595f..3213772 100644
--- a/clients/gplan.inc
+++ b/clients/gplan.inc
@@ -86,6 +86,18 @@ class AppointmentsGPlanClient extends AppointmentsClientApi {
     return $this->products;
   }
 
+  /**
+   * This gives the product list.
+   *
+   * This function is used by the wa_product component.
+   * You can apply filtering in this function.
+   * The fallback will be all products.
+   */
+  public function get_filtered_available_products() {
+    $products = $this->get_available_products();
+    return $products;
+  }
+
   public function get_product_details($product_id) {
     $productDetails = $this->call('getGovProductDetails', array(
       'productID' => $product_id
diff --git a/clients/gplan_multiple.inc b/clients/gplan_multiple.inc
index 25df1fa..8936808 100644
--- a/clients/gplan_multiple.inc
+++ b/clients/gplan_multiple.inc
@@ -4,6 +4,7 @@ class AppointmentsGPlanMultipleClient extends AppointmentsClientApi {
 
   protected $location_id;
   protected $products;
+  protected $locations;
   protected $api_method= 'soap';
 
   const APPOINTMENT_STATUS_BOOKED                      =  0;
@@ -78,6 +79,13 @@ class AppointmentsGPlanMultipleClient extends AppointmentsClientApi {
         if (!empty($details->out->appDuration)) {
           $this->products[$key]['duration'] = $details->out->appDuration;
         }
+        // Check if locations are there.
+        if ($this->get_gov_locations()) {
+          // Get the products that are available per location.
+          if ($products = $this->call('getGovLocationsForProduct', ['productID' => $key])) {
+            $this->products[$key]['locations'] = $products->location;
+          }
+        }
       }
     }
 
@@ -86,6 +94,124 @@ class AppointmentsGPlanMultipleClient extends AppointmentsClientApi {
     return $this->products;
   }
 
+  /**
+   * This gives the product list.
+   *
+   * This function is used by the wa_product component.
+   * You can apply filtering in this function.
+   * The fallback will be all products.
+   */
+  public function get_filtered_available_products() {
+    $products = $this->get_available_products();
+
+    foreach ($products as $key => $product) {
+      // Remove product if there is no location.
+      if (empty($products[$key]['locations'])) {
+        unset($products[$key]);
+      }
+    }
+
+    return $products;
+  }
+
+  /**
+   * This returns the locations.
+   */
+  public function get_gov_locations() {
+    if ($this->locations) {
+      return $this->locations;
+    }
+
+    $this->locations = array();
+
+    // Get all the locations.
+    if ($locations = $this->call('getGovLocations')) {
+      foreach ($locations->locationIDs as $location_id) {
+        $this->locations[$location_id] = [
+          'id' => $location_id,
+        ];
+        // Get the locations detail information.
+        if ($details = $this->call('getGovLocationDetails', array('locationID' => $location_id))) {
+          $this->locations[$location_id]['detail'] = $details->locaties;
+        }
+      }
+    }
+
+    return $this->locations;
+  }
+
+  /**
+   * This gives the location list.
+   *
+   * This function is used by the wa_location component.
+   * You can apply filtering in this function.
+   * The fallback will be all locations.
+   */
+  public function get_filtered_locations($products = FALSE) {
+    $locations = $this->get_gov_locations();
+
+    // Filter locations by products.
+    if ($products) {
+      $filter_products = [];
+      // Loop all products.
+      $product_list = $this->get_filtered_available_products();
+      foreach ($product_list as $value => $product) {
+        // Loop through given products.
+        foreach ($products as $product_id) {
+          if ($value == $product_id['id']) {
+            $product_locations = array();
+            foreach ($product_list[$value]['locations'] as $key => $location) {
+              $product_locations[$key] = $location->locationID;
+            }
+            $filter_products[$value] = $product_locations;
+          }
+        }
+      }
+      // Loop all filtered products.
+      foreach ($filter_products as $key => $product_location) {
+        // Loop all locations.
+        foreach ($locations as $key2 => $location) {
+          // Check if location id matches product location id.
+          if (in_array($location['id'], $product_location)) {
+            $locations[$key2]['available_products'][$key] = $key;
+          }
+          else {
+            $locations[$key2]['unavailable_products'][$key] = $key;
+          }
+        }
+      }
+    }
+
+    return $locations;
+  }
+
+  /**
+   * This returns locations details.
+   *
+   * @param $location_id
+   *
+   * @return mixed location
+   */
+  public function get_location_details($location_id) {
+    $this->get_gov_locations();
+
+    if ($this->locations[$location_id]) {
+      return $this->locations[$location_id];
+    }
+
+    return FALSE;
+  }
+
+  /**
+   * This function is used to override the location.
+   * By default it will use location set in the constructor.
+   *
+   * @param $location_id
+   */
+  public function set_location($location_id) {
+    $this->location_id = $location_id;
+  }
+
   public function get_product_details($product_id) {
     $productDetails = $this->call('getGovProductDetails', array(
       'productID' => $product_id
diff --git a/clients/orchestra.inc b/clients/orchestra.inc
index 9a50ce7..208d71e 100644
--- a/clients/orchestra.inc
+++ b/clients/orchestra.inc
@@ -64,6 +64,32 @@ class AppointmentsOrchestraClient extends AppointmentsClientApi {
     return $products;
   }
 
+  /**
+   * This gives the product list.
+   *
+   * This function is used by the wa_product component.
+   * You can apply filtering in this function.
+   * The fallback will be all products.
+   */
+  public function get_filtered_available_products() {
+    $products = $this->get_available_products();
+    return $products;
+  }
+
+  /**
+   * This returns the locations.
+   */
+  public abstract function get_gov_locations();
+
+  /**
+   * This can not be implemented.
+   *
+   * @param $location_id
+   *
+   * @return bool location
+   */
+  public abstract function get_location_details($location_id);
+
   protected function get_available_appointment_days($product_id, $count) {
     $rest_url_parameters['numberOfCustomers'] = $count;
     $available_appointment_days = $this->call('getAvailableAppointmentDays', array(
@@ -110,17 +136,17 @@ class AppointmentsOrchestraClient extends AppointmentsClientApi {
   public function get_times_by_date($product_ids, $durations, $persons, $date) {
     $dates_all = array();
     foreach ($product_ids as $product_link_id) {
-        $date = substr($date, 0, strpos($date, 'T')) . 'T00:00:00';
-        $time = $this->get_available_appointment_times($product_link_id, $persons[$product_link_id], $date);
-        if (!isset($dates_all[$product_link_id])) {
-          $dates_all[$product_link_id] = array();
-          $dates_all[$product_link_id]['dates'] = array();
-          $dates_all[$product_link_id]['product_id'] = $product_link_id;
-          $dates_all[$product_link_id]['duration'] = $durations[$product_link_id];
-        }
-        if (!isset($dates_all[$product_link_id]['dates'][$date])) {
-          $dates_all[$product_link_id]['dates'][$date] = is_array($time) ? $time : array($time);
-        }
+      $date = substr($date, 0, strpos($date, 'T')) . 'T00:00:00';
+      $time = $this->get_available_appointment_times($product_link_id, $persons[$product_link_id], $date);
+      if (!isset($dates_all[$product_link_id])) {
+        $dates_all[$product_link_id] = array();
+        $dates_all[$product_link_id]['dates'] = array();
+        $dates_all[$product_link_id]['product_id'] = $product_link_id;
+        $dates_all[$product_link_id]['duration'] = $durations[$product_link_id];
+      }
+      if (!isset($dates_all[$product_link_id]['dates'][$date])) {
+        $dates_all[$product_link_id]['dates'][$date] = is_array($time) ? $time : array($time);
+      }
     }
 
     $right_dates_time = $this->_check_consecutive_appointments($dates_all);
diff --git a/components/wa_location.inc b/components/wa_location.inc
new file mode 100644
index 0000000..925dcb2
--- /dev/null
+++ b/components/wa_location.inc
@@ -0,0 +1,153 @@
+<?php
+
+/**
+ * @file
+ * WA location component.
+ */
+
+/**
+ * Implements _webform_defaults_COMPONENT().
+ */
+function _webform_defaults_wa_location() {
+  return array(
+    'name' => '',
+    'form_key' => NULL,
+    'required' => 0,
+    'pid' => 0,
+    'weight' => 0,
+    'value' => '',
+    'extra' => array(
+      'items' => '',
+      'multiple' => NULL,
+      'aslist' => NULL,
+      'empty_option' => '',
+      'optrand' => 0,
+      'other_option' => NULL,
+      'other_text' => t('Other...'),
+      'title_display' => 0,
+      'description' => '',
+      'description_above' => FALSE,
+      'custom_keys' => FALSE,
+      'options_source' => '',
+      'private' => FALSE,
+      'analysis' => TRUE,
+    ),
+  );
+}
+
+/**
+ * Implements _webform_edit_COMPONENT().
+ */
+function _webform_edit_wa_location($component) {
+  return array('extra' => array());
+}
+
+/**
+ * Implements _webform_render_COMPONENT().
+ */
+function _webform_render_wa_location($component, $value = NULL, $filter = TRUE) {
+
+  $form_item = array(
+    '#type' => 'wa_location',
+    '#title' => $filter ? webform_filter_xss($component['name']) : $component['name'],
+    '#required' => $component['required'],
+    '#weight' => $component['weight'],
+    '#description'   => $filter ? webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'],
+    '#default_value' => $filter ? webform_replace_tokens($component['value']) : $component['value'],
+    '#prefix' => '<div class="webform-component-wa-location" id="webform-component-' . $component['form_key'] . '">',
+    '#suffix' => '</div>',
+  );
+
+  if (!empty($value)) {
+    $form_item['#default_value'] = $value;
+  }
+
+  return $form_item;
+}
+
+/**
+ * Implements _webform_display_COMPONENT().
+ */
+function _webform_display_wa_location($component, $value, $format = 'html') {
+  $location = dvg_appointments_get_location_information($value['location']);
+  return array(
+    '#title' => $component['name'],
+    '#weight' => $component['weight'],
+    '#required' => $component['required'],
+    '#theme' => 'webform_display_textfield',
+    '#theme_wrappers' => $format == 'html' ? array('webform_element') : array('webform_element_text'),
+    '#post_render' => array('webform_element_wrapper'),
+    '#component' => $component,
+    '#format' => $format,
+    '#value' => $location,
+  );
+}
+
+/**
+ * Returns HTML for the product/count fields on form.
+ */
+function theme_dvg_appointments_location($variables) {
+  $element = $variables['element'];
+  return $element['#children'];
+}
+
+/**
+ * Element process callback for the wa_location elements.
+ */
+function dvg_appointments_location_element_process($element, &$form_state, $form) {
+  $client = dvg_appointments_get_client_api();
+  $selected_products = dvg_appointments_get_selected_products($form_state, $form);
+
+  $available_locations = $client->get_filtered_locations($selected_products);
+
+  foreach ($available_locations as $location) {
+    if (count($selected_products) == count($location['available_products']) && !array_key_exists('unavailable_products', $location)) {
+      $location_options[$location['id']] = $location['detail']->locationDesc;
+    }
+  }
+
+  if (count($location_options) < 0) {
+    drupal_set_message(t("This combination can't be planned on one location. Create an appointment for each product."), 'warning');
+  }
+
+  if (count($available_locations) > count($location_options)) {
+    drupal_set_message(t("Not every location is available for your appointment. You're appointment can only be made with the following location(s)."), 'info');
+  }
+
+  if (count($location_options) > 5) {
+    $location_options = array_unshift($location_options, array('' => t('Select a location')));
+    $element['location'] = array(
+      '#type' => 'select',
+      '#title' => t('Location'),
+      '#required' => TRUE,
+      '#options' => $location_options,
+      '#attributes' => array('class' => array('wa-location')),
+    );
+  }
+  else {
+    $element['location'] = array(
+      '#type' => 'radios',
+      '#title' => t('Location'),
+      '#required' => TRUE,
+      '#options' => $location_options,
+      '#attributes' => array('class' => array('wa-location')),
+    );
+  }
+
+  if (!empty($element['#default_value']['location'])) {
+    $element['location']['#default_value'] = $element['#default_value']['location'];
+  }
+
+  return $element;
+}
+
+/**
+ * Element validate callback for the wa_location elements.
+ */
+function dvg_appointments_location_element_validate($element, &$form_state) {
+  $form_key = $element['#webform_component']['form_key'];
+
+  if (empty($form_state['values']['submitted'][$form_key]['location'])) {
+    form_error($element['location'], t("You haven't filled in the location."));
+  }
+}
diff --git a/dvg_appointments.client.inc b/dvg_appointments.client.inc
index 9bf3bea..e219446 100644
--- a/dvg_appointments.client.inc
+++ b/dvg_appointments.client.inc
@@ -117,6 +117,24 @@ abstract class AppointmentsClientApi {
 
   abstract public function get_available_products();
 
+  abstract public function get_filtered_available_products();
+
+  public function get_gov_locations() {
+    return array();
+  }
+
+  public function get_filtered_locations($products) {
+    return array();
+  }
+
+  public function get_location_details($location_id) {
+    return FALSE;
+  }
+
+  public function set_location($location_id) {
+    return FALSE;
+  }
+
   public function get_product_details($product_id) {
     return '';
   }
diff --git a/dvg_appointments.module b/dvg_appointments.module
index 371f18f..4355151 100644
--- a/dvg_appointments.module
+++ b/dvg_appointments.module
@@ -173,6 +173,14 @@ function dvg_appointments_webform_component_info() {
       'required' => TRUE,
     ),
   );
+  $components['wa_location'] = array(
+    'label' => t('Appointment location'),
+    'description' => t('Appointment location.'),
+    'file' => 'components/wa_location.inc',
+    'features' => array(
+      'required' => TRUE,
+    ),
+  );
   $components['wa_date_time'] = array(
     'label' => t('Appointment date/time'),
     'description' => t('Appointment date/time selection.'),
@@ -341,7 +349,7 @@ function _webform_display_wa_product($component, $values, $format = 'html') {
   }
 
   $client = dvg_appointments_get_client_api();
-  $products = $client->get_available_products();
+  $products = $client->get_filtered_available_products();
   $display = array(
     '#title' => $component['name'],
     '#weight' => $component['weight'],
@@ -728,6 +736,15 @@ function dvg_appointments_field_widget_info() {
         'default value' => FIELD_BEHAVIOR_NONE,
       ),
     ),
+    'wa_location' => array(
+      'label' =>  t('Appointment location'),
+      'field types' => array('wa_location'),
+      'settings' => array(),
+      'behaviors' => array(
+        'multiple values' => FIELD_BEHAVIOR_DEFAULT,
+        'default value' => FIELD_BEHAVIOR_NONE,
+      ),
+    ),
     'wa_date_time' => array(
       'label' =>  t('Appointment date/time'),
       'field types' => array('wa_date_time'),
@@ -762,6 +779,13 @@ function dvg_appointments_element_info() {
       '#element_validate' => array('dvg_appointments_product_element_validate'),
       '#theme_wrappers' => array('dvg_appointments_product'),
     ),
+    'wa_location' => array(
+      '#input' => TRUE,
+      '#delta' => 0,
+      '#process' => array('dvg_appointments_location_element_process'),
+      '#element_validate' => array('dvg_appointments_location_element_validate'),
+      '#theme_wrappers' => array('dvg_appointments_location'),
+    ),
     'wa_date_time' => array(
       '#input' => TRUE,
       '#delta' => 0,
@@ -786,7 +810,7 @@ function dvg_appointments_product_element_process($element, &$form_state, $form)
   $product_options = array('' => t('Select a product'));
   $invisible_values = array(array('value' => ''));
 
-  $available_products = $client->get_available_products();
+  $available_products = $client->get_filtered_available_products();
   // Let other modules lookup the appointment.
   drupal_alter('dvg_appointments_available_products', $available_products, $element, $form_state, $form);
 
@@ -916,6 +940,20 @@ function dvg_appointments_get_selected_products($form_state, $form) {
 }
 
 /**
+ * Helper function that fetches the selected location from the form_state.
+ */
+function dvg_appointments_get_selected_location($form_state, $form) {
+  $location = FALSE;
+
+  $cid = dvg_appointments_get_cid($form['#node'], 'wa_location');
+  if ($cid && !empty($form_state['storage']['submitted'][$cid])) {
+    $location = $form_state['storage']['submitted'][$cid]['location'];
+  }
+
+  return $location;
+}
+
+/**
  * Helper function that fetches the selected products from the form_state.
  */
 function dvg_appointments_get_selected_slot($form_state, $form) {
@@ -933,7 +971,7 @@ function dvg_appointments_get_selected_slot($form_state, $form) {
 function dvg_appointments_date_time_element_process($element, &$form_state, $form) {
   $client_api = dvg_appointments_get_client_api();
   $selected_products = dvg_appointments_get_selected_products($form_state, $form);
-
+  $selected_location = dvg_appointments_get_selected_location($form_state, $form);
   $product_link_ids = $product_names = $products_durations = $persons = array();
   foreach ($selected_products as $selected_product) {
     $product_id = $selected_product['id'];
@@ -970,7 +1008,7 @@ function dvg_appointments_date_time_element_process($element, &$form_state, $for
 
   drupal_alter('dvg_appointments_date_time', $client_api, $form_state);
 
-  $dates_all = _dvg_appointments_load_date_time_dates($element, $form_state, $product_link_ids, $products_durations, $persons);
+  $dates_all = _dvg_appointments_load_date_time_dates($element, $form_state, $product_link_ids, $products_durations, $persons, $selected_location);
   $dates = array();
   foreach ($dates_all as $unic_id => $date_array) {
     if ($unic_id == 0 || $date_array[0]['date'] != $dates_all[$unic_id - 1][0]['date']) {
@@ -1057,10 +1095,15 @@ function dvg_appointments_date_time_element_process($element, &$form_state, $for
 /**
  * Helper for loading the dates used for filling the wa_date_time webform component.
  */
-function _dvg_appointments_load_date_time_dates($element, $form_state, $product_ids, $products_durations, $persons) {
+function _dvg_appointments_load_date_time_dates($element, $form_state, $product_ids, $products_durations, $persons, $location = FALSE) {
   $client_api = dvg_appointments_get_client_api();
   $overrides = module_invoke_all('appointment_date_overrides');
 
+  // Location has been set and the location should be overridden in the client.
+  if ($location) {
+    $client_api->set_location($location);
+  }
+
   // Default dates.
   $dates = $client_api->get_dates_times($product_ids, $products_durations, $persons);
   if (!empty($overrides) && is_array($overrides)) {
@@ -1262,6 +1305,10 @@ function dvg_appointments_theme() {
     'dvg_appointments_product' => array(
       'render element' => 'element',
     ),
+    'dvg_appointments_location' => array(
+      'render element' => 'element',
+      'file' => 'components/wa_location.inc',
+    ),
     'dvg_appointments_date_time' => array(
       'render element' => 'element',
     ),
@@ -1461,6 +1508,16 @@ function _dvg_appointments_table(DvgAppointment $appointment, $table = TRUE) {
 
   $rows = array_merge($product_rows, $additional_rows);
 
+  if ($location = $appointment->getLocation()) {
+    $location_row = array(
+      array(
+        array('class' => array('info-label'), 'data' => t('Location')),
+        $location,
+      ),
+    );
+    $rows = array_merge($rows, $location_row);
+  }
+
   if ($appointment->getId()) {
     $rows[] = array(
       array('class' => array('info-label'), 'data' => t('Appointment id')),
@@ -1510,8 +1567,14 @@ function dvg_appointments_form_webform_client_form_alter(&$form, &$form_state) {
     }
 
     $wa_product = dvg_appointments_get_cid($node, 'wa_product');
+    $wa_location_cid = dvg_appointments_get_cid($node, 'wa_location');
     if ($wa_product && $form_state['webform']['page_num'] == $node->webform['components'][$wa_product]['page_num']) {
-      $form['#validate'][] = 'dvg_appointments_validate_available_date_time';
+      if (!$wa_location_cid) {
+        $form['#validate'][] = 'dvg_appointments_validate_available_date_time';
+      }
+      else {
+        $form['#validate'][] = 'dvg_appointments_validate_available_date_time_location';
+      }
     }
 
     if ($wa_products && $preview_enabled && $last_page) {
@@ -1523,9 +1586,14 @@ function dvg_appointments_form_webform_client_form_alter(&$form, &$form_state) {
         $additional_customer_duration = isset($product['additional_customer_duration']) ? $product['additional_customer_duration'] : $product['duration'];
         $fake_appointment->addProduct($product['id'], $product['count'], $product['duration'] * 60, $additional_customer_duration * 60);
       }
-
       $duration = $fake_appointment->getAppointmentDurationEstimate();
       $fake_appointment->setEnd(DateTime::createfromformat('U', $start_time + $duration));
+      // Get the location.
+      if ($location_id = dvg_appointments_get_selected_location($form_state, $form)) {
+        $wa_location_id = dvg_appointments_get_location_information($location_id);
+        $fake_appointment->setLocation($wa_location_id);
+      }
+
       $product_tables[] = _dvg_appointments_table($fake_appointment);
 
       $form['wa_product'] = array(
@@ -1558,7 +1626,6 @@ function dvg_appointments_form_webform_client_form_alter(&$form, &$form_state) {
       }
     }
   }
-
   elseif ($node->nid == functional_content_nid('dvg_appointments_cancel')) {
     $form['#attributes']['class'][] = 'appointment-webform';
 
@@ -1630,6 +1697,72 @@ function dvg_appointments_validate_available_date_time(&$form, &$form_state) {
 }
 
 /**
+ * Validation handler that checks available times for the selected product(s).
+ */
+function dvg_appointments_validate_available_date_time_location(&$form, &$form_state) {
+  // Only validate when the next-button is pressed.
+  if ($form['actions']['next']['#value'] != $form_state['triggering_element']['#value']) {
+    return;
+  }
+
+  if (!form_get_errors()) {
+    $client_api = dvg_appointments_get_client_api();
+
+    $cid = dvg_appointments_get_cid($form['#node'], 'wa_product');
+    $form_key = $form['#node']->webform['components'][$cid]['form_key'];
+    $products = array();
+    if (isset($form_state['values'])) {
+      if (_wfm_is_multiple($form['submitted'][$form_key]['#webform_component'])) {
+        // Parsing components that can have multiple values.
+        foreach ($form_state['values']['submitted'][$form_key] as $key => $value) {
+          if (is_numeric($key) && is_array($value)) {
+            $products[] = $value;
+          }
+        }
+      }
+      else {
+        // Parsing components that can have a single value.
+        if (is_array($form_state['values']['submitted'][$form_key])) {
+          $products[] = $form_state['values']['submitted'][$form_key];
+        }
+      }
+    }
+
+    $form_state['storage']['submitted'][$cid] = $products;
+    $selected_products = dvg_appointments_get_selected_products($form_state, $form);
+
+    $product_link_ids = $products_durations = $persons = array();
+    foreach ($selected_products as $selected_product) {
+      $product_id = $selected_product['id'];
+
+      $product_link_ids[] = $product_id;
+      $persons[$product_id] = $selected_product['count'];
+      if (isset($selected_product['additional_customer_duration']) && $selected_product['count'] > 1) {
+        $total_product_duration = $selected_product['duration'] + $selected_product['additional_customer_duration'] * ($selected_product['count'] - 1);
+      }
+      else {
+        $total_product_duration = $selected_product['duration'] * $selected_product['count'];
+      }
+      $products_durations[$product_id] = $total_product_duration;
+    }
+
+    $dates_available = FALSE;
+    $available_locations = $client_api->get_filtered_locations($selected_products);
+
+    foreach ($available_locations as $key => $available_location) {
+      $client_api->set_location($available_location['id']);
+      if ($client_api->get_dates_times($product_link_ids, $products_durations, $persons)) {
+        $dates_available = TRUE;
+      }
+    }
+
+    if (!$dates_available) {
+      form_set_error('wa_product', t('No suitable date and time for this request. Please register appointments separately.'));
+    }
+  }
+}
+
+/**
  * Validation handler for webforms.
  */
 function dvg_appointments_book_appointment(&$form, &$form_state) {
@@ -1657,6 +1790,12 @@ function dvg_appointments_book_appointment(&$form, &$form_state) {
     'products' => $products,
   );
 
+  $location = dvg_appointments_get_selected_location($form_state, $form);
+  // Location has been set and the location should be overridden in the client.
+  if ($location) {
+    $client_api->set_location($location);
+  }
+
   try {
     $booked_appointment = $client_api->book_appointment($app_data, $book_data);
 
@@ -1772,6 +1911,18 @@ function dvg_appointments_get_appointments($nid, $sid) {
 }
 
 /**
+ * Helper function that gets the location desc.
+ */
+function dvg_appointments_get_location_information($location_id){
+  $client_api = dvg_appointments_get_client_api();
+  $details = $client_api->get_location_details($location_id);
+  if ($details) {
+    return $details['detail']->locationDesc;
+  }
+  return FALSE;
+}
+
+/**
  * Helper function that renders additional confirmation text for the products.
  */
 function _dvg_appointments_get_task_confirm_text_by_product_code($product_code) {
@@ -1852,7 +2003,13 @@ function dvg_appointments_preprocess_webform_confirmation(&$vars) {
     if ($wa_appointment_cid) {
       $submission = webform_get_submission($node->nid, $vars['sid']);
       $appointment = $submission->data[$wa_appointment_cid]['appointment'];
-
+      // Add Location to the appointment.
+      if ($wa_location = dvg_appointments_get_cid($node, 'wa_location')) {
+        $location_id = $submission->data[$wa_location]['location'];
+        if ($location = dvg_appointments_get_location_information($location_id)) {
+          $appointment->setLocation($location);
+        }
+      }
       $markup = array(
         '#markup' => _dvg_appointments_table($appointment),
       );
@@ -2020,6 +2177,10 @@ function dvg_appointments_token_info() {
     'name' => t('Appointment confirmation date'),
     'description' => t('The date of the appointment'),
   );
+  $info['tokens']['submission']['dvg_appointments_location'] = array(
+    'name' => t('Appointment Location'),
+    'description' => t('The location information'),
+  );
 
   return $info;
 }
@@ -2046,6 +2207,15 @@ function dvg_appointments_tokens($type, $tokens, array $data = array(), array $o
           $cid = dvg_appointments_get_cid($node, 'wa_appointment');
           if ($cid) {
             $appointment = $submission->data[$cid]['appointment'];
+            // Add Location to the appointment.
+            if ($wa_location = dvg_appointments_get_cid($node, 'wa_location')) {
+              if ($wa_location) {
+                $location_id = $submission->data[$wa_location]['location'];
+                if ($location = dvg_appointments_get_location_information($location_id)) {
+                  $appointment->setLocation($location);
+                }
+              }
+            }
             if ($html) {
               $replacements[$original] = _dvg_appointments_table($appointment, TRUE);
             }
@@ -2086,6 +2256,20 @@ function dvg_appointments_tokens($type, $tokens, array $data = array(), array $o
 
           $replacements[$original] = dvg_appointments_format_date($timestamp, 'date');
           break;
+
+        case 'dvg_appointments_location':
+          if ($wa_location = dvg_appointments_get_cid($node, 'wa_location')) {
+            $location_id = $submission->data[$wa_location]['location'];
+            $location = dvg_appointments_get_location_information($location_id);
+          }
+          // Check for location.
+          if ($location) {
+            $replacements[$original] = $location;
+          }
+          else {
+            $replacements[$original] = t("Location is not available.");
+          }
+          break;
       }
     }
   }
