-
-
{l s='Invoice address'}
- {if $can_edit}
-
- {/if}
-
-
-
-
-
- {l s='Edit'}
-
- {displayAddressDetail address=$addresses.invoice newLine='
'}
- {if $addresses.invoice->other}
-
{$addresses.invoice->other}
+
+
+
+
+
{l s='Customer Address'}
+ {if $can_edit}
+ {if $idOrderAddressInvoice}
+
+ {if (!$idCurrentAddress || ($idCurrentAddress != $idOrderAddressInvoice)) || $ordersWithDiffInvAddr}
+
+ {if !$idCurrentAddress || ($idCurrentAddress != $idOrderAddressInvoice)}
+
{l s='Set as current address'}
+ {/if}
+
+ {/if}
+ {else}
+
+ {if $idCurrentAddress}
+
+ {/if}
+ {/if}
+ {/if}
+
+
+ {if $guestFormattedAddress}
+ {$guestFormattedAddress}
+ {else}
+
+
+
+ {l s='Guest address not found.'}
-
+ {/if}
-
{* Order Internal notes *}
diff --git a/classes/Address.php b/classes/Address.php
index 48a30bd26..5a0bd2498 100644
--- a/classes/Address.php
+++ b/classes/Address.php
@@ -180,7 +180,7 @@ class AddressCore extends ObjectModel
{
// for customer address we need to check of customer address already exists.
if ($this->id_customer) {
- if ($id_address = Customer::getCustomerIdAddress($this->id_customer, false)) {
+ if ($this->deleted == 0 && $id_address = Customer::getCustomerIdAddress($this->id_customer, false)) {
return false;
}
}
@@ -196,6 +196,8 @@ class AddressCore extends ObjectModel
public function update($null_values = false)
{
+
+ $context = Context::getContext();
// Empty related caches
if (isset(self::$_idCountries[$this->id])) {
unset(self::$_idCountries[$this->id]);
@@ -208,9 +210,42 @@ class AddressCore extends ObjectModel
Customer::resetAddressCache($this->id_customer, $this->id);
}
+ // If address is already used in any order, it will not be edited directly, set address to "deleted" and create a new address
+ if ($this->isUsed() && $this->deleted == 0) {
+ return $this->updateUsedAddress($this);
+ }
+
return parent::update($null_values);
}
+ /**
+ * If address is already used in any order
+ * set address to "deleted" and create a new address
+ * @param Address $address
+ * @return bool
+ */
+ public function updateUsedAddress(Address $address)
+ {
+ $objOldAddress = new Address($address->id);
+ $address->id = $address->id_address = null;
+
+ if ($objOldAddress->delete() && $address->save()) {
+ // we need to change the address id in the current cart as the deleted ID can assigned in context->cart.
+ if ($customerCarts = Cart::getCustomerCarts($objOldAddress->id_customer, false)) {
+ foreach ($customerCarts as $cart) {
+ $objCart = new Cart($cart['id_cart']);
+ if ($cart['id_address_invoice'] == $objOldAddress->id) {
+ $objCart->updateAddressId($objOldAddress->id, $address->id);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
/**
* @see ObjectModel::delete()
*/
@@ -222,12 +257,12 @@ class AddressCore extends ObjectModel
// reset checkout process if addresses deletes
CheckoutProcess::refreshCheckoutProcess();
- if (!$this->isUsed()) {
- return parent::delete();
- } else {
+ if ($this->isUsed()) {
$this->deleted = true;
return $this->update();
}
+
+ return parent::delete();
}
/**
@@ -252,10 +287,9 @@ class AddressCore extends ObjectModel
// for customer address we need to check of customer address already exists.
// if we are editing an address we do not need to validate already created address.
- if (!Validate::isLoadedObject($this)) {
+ if (!Validate::isLoadedObject($this) && $this->deleted != 0) {
if ($idCustomer = Tools::getValue('id_customer')) {
if ($id_address = Customer::getCustomerIdAddress($idCustomer)) {
-
$errors[] = sprintf(Tools::displayError('Customer address already exists. Id address: #%d'), $id_address);
}
}
diff --git a/classes/order/Order.php b/classes/order/Order.php
index a7d083ff6..3b64e3df4 100644
--- a/classes/order/Order.php
+++ b/classes/order/Order.php
@@ -602,13 +602,19 @@ class OrderCore extends ObjectModel
$is_booking = null,
$product_service_type = null,
$product_auto_add = null,
- $product_price_addition_type = null
+ $product_price_addition_type = null,
+ $ids_order_detail = []
) {
$sql = 'SELECT *
FROM `'._DB_PREFIX_.'order_detail` od
LEFT JOIN `'._DB_PREFIX_.'product` p ON (p.id_product = od.product_id)
LEFT JOIN `'._DB_PREFIX_.'product_shop` ps ON (ps.id_product = p.id_product AND ps.id_shop = od.id_shop)
WHERE od.`id_order` = '.(int)$this->id;
+
+ if ($ids_order_detail) {
+ $sql .= ' AND od.`id_order_detail` IN ('.implode(',', $ids_order_detail).')';
+ }
+
if ($is_booking !== null) {
$sql .= ' AND od.`is_booking_product` = '. (int)$is_booking;
if (!$is_booking && $product_service_type !== null) {
@@ -954,21 +960,30 @@ class OrderCore extends ObjectModel
*
* @param int $id_customer Customer id
* @param bool $show_hidden_status Display or not hidden order statuses
+ * @param bool $skip_id_address_invoice Skip orders from this id_address_invoice
* @return array Customer orders
*/
- public static function getCustomerOrders($id_customer, $show_hidden_status = false, Context $context = null)
+ public static function getCustomerOrders($id_customer, $show_hidden_status = false, Context $context = null, $id_address_invoice = null, $skip_address = 0)
{
if (!$context) {
$context = Context::getContext();
}
- $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
- SELECT o.*, (SELECT SUM(od.`product_quantity`) FROM `'._DB_PREFIX_.'order_detail` od WHERE od.`id_order` = o.`id_order`) nb_products
+ $sql = 'SELECT o.*, (SELECT SUM(od.`product_quantity`) FROM `'._DB_PREFIX_.'order_detail` od WHERE od.`id_order` = o.`id_order`) nb_products
FROM `'._DB_PREFIX_.'orders` o
- WHERE o.`id_customer` = '.(int)$id_customer.
- Shop::addSqlRestriction(Shop::SHARE_ORDER).'
+ WHERE o.`id_customer` = '.(int)$id_customer;
+
+ // if you want orders from / not from a specific id_address_invoice
+ if (!is_null($id_address_invoice)) {
+ $sql .= ' AND o.`id_address_invoice`';
+ $sql .= ($skip_address ? ' != ' : ' = ').(int)$id_address_invoice;
+ }
+
+ $sql .= Shop::addSqlRestriction(Shop::SHARE_ORDER).'
GROUP BY o.`id_order`
- ORDER BY o.`date_add` DESC');
+ ORDER BY o.`date_add` DESC';
+
+ $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
if (!$res) {
return array();
}
@@ -1091,11 +1106,12 @@ class OrderCore extends ObjectModel
$bookingProducts = null,
$product_service_type = null,
$product_auto_add = null,
- $product_price_addition_type = null
+ $product_price_addition_type = null,
+ $ids_order_detail = []
) {
// update
if (!$products) {
- $products = $this->getProductsDetail($bookingProducts, $product_service_type, $product_auto_add, $product_price_addition_type);
+ $products = $this->getProductsDetail($bookingProducts, $product_service_type, $product_auto_add, $product_price_addition_type, $ids_order_detail);
}
$return = 0;
@@ -1116,11 +1132,12 @@ class OrderCore extends ObjectModel
$bookingProducts = null,
$product_service_type = null,
$product_auto_add = null,
- $product_price_addition_type = null
+ $product_price_addition_type = null,
+ $ids_order_detail = []
) {
/* Retro-compatibility (now set directly on the validateOrder() method) */
if (!$products) {
- $products = $this->getProductsDetail($bookingProducts, $product_service_type, $product_auto_add, $product_price_addition_type);
+ $products = $this->getProductsDetail($bookingProducts, $product_service_type, $product_auto_add, $product_price_addition_type, $ids_order_detail);
}
$return = 0;
diff --git a/classes/order/OrderInvoice.php b/classes/order/OrderInvoice.php
index b1f8d1ce9..509d77d3b 100644
--- a/classes/order/OrderInvoice.php
+++ b/classes/order/OrderInvoice.php
@@ -413,7 +413,7 @@ class OrderInvoiceCore extends ObjectModel
// - 'total_price_tax_excl'
// - 'total_amount'
$breakdown = array();
- $order_detail = $order->getOrderDetailList();
+ $order_detail = $this->getProducts();
$order_detail = array_filter($order_detail, function($v) {
return ($v['is_booking_product']
|| ($v['product_auto_add']
@@ -482,7 +482,7 @@ class OrderInvoiceCore extends ObjectModel
// - 'total_price_tax_excl'
// - 'total_amount'
$breakdown = array();
- $order_detail = $order->getOrderDetailList();
+ $order_detail = $this->getProducts();
$order_detail = array_filter($order_detail, function($v) {
return (!$v['is_booking_product'] && !$v['product_auto_add'] && $v['product_service_type'] == Product::SERVICE_PRODUCT_WITH_ROOMTYPE);
});
@@ -546,7 +546,7 @@ class OrderInvoiceCore extends ObjectModel
// - 'total_price_tax_excl'
// - 'total_amount'
$breakdown = array();
- $order_detail = $order->getOrderDetailList();
+ $order_detail = $this->getProducts();
$order_detail = array_filter($order_detail, function($v) {
return (!$v['is_booking_product']
&& $v['product_auto_add']
@@ -616,7 +616,7 @@ class OrderInvoiceCore extends ObjectModel
// - 'total_price_tax_excl'
// - 'total_amount'
$breakdown = array();
- $order_detail = $order->getOrderDetailList();
+ $order_detail = $this->getProducts();
$order_detail = array_filter($order_detail, function($v) {
return (!$v['is_booking_product'] && $v['product_service_type'] == Product::SERVICE_PRODUCT_WITHOUT_ROOMTYPE);
});
@@ -674,8 +674,10 @@ class OrderInvoiceCore extends ObjectModel
$order = $this->getOrder();
}
$breakdown = array();
+ $order_details = $this->getProducts();
$objBookingDemand = new HotelBookingDemands();
- $details = $objBookingDemand->getExtraDemandsTaxesDetails($order->id);
+ $order_details = array_column($order_details, 'id_order_detail');
+ $details = $objBookingDemand->getExtraDemandsTaxesDetails($order->id, $order_details);
if (!$this->useOneAfterAnotherTaxComputationMethod()) {
$grouped_details = array();
foreach ($details as $row) {
@@ -1013,7 +1015,7 @@ class OrderInvoiceCore extends ObjectModel
$payments = OrderPaymentDetail::getByInvoiceId($this->id);
foreach ($payments as $payment) {
/** @var OrderPayment $payment */
- $amount += $payment['amount'];
+ $amount += ($payment['amount'] / $payment['conversion_rate']);
}
Cache::store($cache_id, $amount);
return $amount;
diff --git a/classes/pdf/HTMLTemplateInvoice.php b/classes/pdf/HTMLTemplateInvoice.php
index fdaeddce9..b134abcee 100644
--- a/classes/pdf/HTMLTemplateInvoice.php
+++ b/classes/pdf/HTMLTemplateInvoice.php
@@ -349,9 +349,9 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate
if ($type_value)
if (isset($customer->id)) {
$cart_obj = new Cart($this->order->id_cart);
- $order_bk_data = $obj_htl_bk_dtl->getOnlyOrderBookingData($this->order->id, $cart_obj->id_guest, $type_value['product_id'], $customer->id);
+ $order_bk_data = $obj_htl_bk_dtl->getOnlyOrderBookingData($this->order->id, $cart_obj->id_guest, $type_value['product_id'], $customer->id, $type_value['id_order_detail']);
} else {
- $order_bk_data = $obj_htl_bk_dtl->getOnlyOrderBookingData($this->order->id, $customer->id_guest, $type_value['product_id']);
+ $order_bk_data = $obj_htl_bk_dtl->getOnlyOrderBookingData($this->order->id, $customer->id_guest, $type_value['product_id'], 0, $type_value['id_order_detail']);
}
$cart_htl_data[$type_key]['id_product'] = $type_value['product_id'];
@@ -396,7 +396,8 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate
$data_v['date_to'],
0,
1,
- 0
+ 0,
+ $type_value['id_order_detail']
);
$cart_htl_data[$type_key]['date_diff'][$date_join]['extra_demands_price_ti'] = $objBookingDemand->getRoomTypeBookingExtraDemands(
$order_obj->id,
@@ -406,7 +407,8 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate
$data_v['date_to'],
0,
1,
- 1
+ 1,
+ $type_value['id_order_detail']
);
$cart_htl_data[$type_key]['date_diff'][$date_join]['additional_services'] = $objRoomTypeServiceProductOrderDetail->getroomTypeServiceProducts(
$order_obj->id,
@@ -549,14 +551,25 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate
$footer['total_extra_demands_te'] = $totalDemandsPriceTE;
}
}
- $footer['room_price_tax_excl'] = $this->order->getTotalProductsWithoutTaxes(false, true) + $this->order->getTotalProductsWithoutTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 1, Product::PRICE_ADDITION_TYPE_WITH_ROOM);
- $footer['room_price_tax_incl'] = $this->order->getTotalProductsWithTaxes(false, true) + $this->order->getTotalProductsWithoutTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 1, Product::PRICE_ADDITION_TYPE_WITH_ROOM);
- // $footer['service_products_price_tax_excl'] = $this->order->getTotalProductsWithoutTaxes(false, false, Product::SERVICE_PRODUCT_WITHOUT_ROOMTYPE);
- // $footer['service_products_price_tax_incl'] = $this->order->getTotalProductsWithTaxes(false, false, Product::SERVICE_PRODUCT_WITHOUT_ROOMTYPE);
- $footer['additional_service_price_tax_excl'] = $this->order->getTotalProductsWithoutTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 0) + $totalDemandsPriceTE;
- $footer['additional_service_price_tax_incl'] = $this->order->getTotalProductsWithTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 0) + $totalDemandsPriceTI;
- $footer['total_convenience_fee_te'] = $this->order->getTotalProductsWithoutTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 1, Product::PRICE_ADDITION_TYPE_INDEPENDENT);
- $footer['total_convenience_fee_ti'] = $this->order->getTotalProductsWithTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 1, Product::PRICE_ADDITION_TYPE_INDEPENDENT);
+
+ $footer['room_price_tax_excl'] = 0;
+ $footer['room_price_tax_incl'] = 0;
+ $footer['additional_service_price_tax_excl'] = 0;
+ $footer['additional_service_price_tax_incl'] =0;
+ $footer['total_convenience_fee_te'] = 0;
+ $footer['total_convenience_fee_ti'] = 0;
+ if ($idsOrderDetail = array_column($order_details, 'id_order_detail')) {
+ $footer['room_price_tax_excl'] = $this->order->getTotalProductsWithoutTaxes(false, true, null, null, null, $idsOrderDetail) + $this->order->getTotalProductsWithoutTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 1, Product::PRICE_ADDITION_TYPE_WITH_ROOM, $idsOrderDetail);
+ $footer['room_price_tax_incl'] = $this->order->getTotalProductsWithTaxes(false, true, null, null, null, $idsOrderDetail) + $this->order->getTotalProductsWithoutTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 1, Product::PRICE_ADDITION_TYPE_WITH_ROOM, $idsOrderDetail);
+ // $footer['service_products_price_tax_excl'] = $this->order->getTotalProductsWithoutTaxes(false, false, Product::SERVICE_PRODUCT_WITHOUT_ROOMTYPE);
+ // $footer['service_products_price_tax_incl'] = $this->order->getTotalProductsWithTaxes(false, false, Product::SERVICE_PRODUCT_WITHOUT_ROOMTYPE);
+ $footer['additional_service_price_tax_excl'] = $this->order->getTotalProductsWithoutTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 0, null, $idsOrderDetail) + $totalDemandsPriceTE;
+ $footer['additional_service_price_tax_incl'] = $this->order->getTotalProductsWithTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 0, null, $idsOrderDetail) + $totalDemandsPriceTI;
+ $footer['total_convenience_fee_te'] = $this->order->getTotalProductsWithoutTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 1, Product::PRICE_ADDITION_TYPE_INDEPENDENT, $idsOrderDetail);
+ $footer['total_convenience_fee_ti'] = $this->order->getTotalProductsWithTaxes(false, false, Product::SERVICE_PRODUCT_WITH_ROOMTYPE, 1, Product::PRICE_ADDITION_TYPE_INDEPENDENT, $idsOrderDetail);
+ }
+ $footer['total_paid_real'] = $this->order_invoice->getTotalPaid();
+
$data = array(
'cart_htl_data' => $cart_htl_data,
'service_product_data' => $service_product_data,
@@ -676,6 +689,7 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate
'ecotax_tax' => $this->order_invoice->getEcoTaxTaxesBreakdown(),
'wrapping_tax' => $this->order_invoice->getWrappingTaxesBreakdown(),
);
+
foreach ($breakdowns as $type => $bd) {
if (empty($bd)) {
unset($breakdowns[$type]);
diff --git a/controllers/admin/AdminAddressesController.php b/controllers/admin/AdminAddressesController.php
index 5f6bb472d..1d4b32e9e 100644
--- a/controllers/admin/AdminAddressesController.php
+++ b/controllers/admin/AdminAddressesController.php
@@ -454,10 +454,8 @@ class AdminAddressesControllerCore extends AdminController
** we delete its id_address to force the creation of a new one */
if ((int)Tools::getValue('id_order')) {
$this->_redirect = false;
- if (isset($_POST['address_type'])) {
- $_POST['id_address'] = '';
- $this->id_object = null;
- }
+ // set deleted=1 as customer can have only one address and this address is for an order only
+ $_POST['deleted'] = 1;
}
// Check the requires fields which are settings in the BO
@@ -478,10 +476,18 @@ class AdminAddressesControllerCore extends AdminController
if ($this->action == 'save' && ($id_order = (int)Tools::getValue('id_order')) && !count($this->errors) && !empty($address_type)) {
if (!Db::getInstance()->Execute('UPDATE '._DB_PREFIX_.'orders SET `id_address_'.bqSQL($address_type).'` = '.(int)$this->object->id.' WHERE `id_order` = '.(int)$id_order)) {
$this->errors[] = Tools::displayError('An error occurred while linking this address to its order.');
- } else {
- Tools::redirectAdmin(urldecode(Tools::getValue('back')).'&conf=4');
}
}
+
+ // in case of save and stay, redirect after save with current address.
+ // Because the current address can not be same as the current one(We have to delete it and create a new one in case address is used in orders)
+ if (empty($this->errors) && Tools::isSubmit('submitAdd'.$this->table.'AndStay')) {
+ $idCurrentAddress = Customer::getCustomerIdAddress($this->object->id_customer, false);
+ if ($idCurrentAddress != $this->object->id) {
+ $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$idCurrentAddress.'&conf=4&update'.$this->table.'&token='.$this->token;
+ }
+ }
+
return $return;
}
diff --git a/controllers/admin/AdminCustomerPreferencesController.php b/controllers/admin/AdminCustomerPreferencesController.php
index 5f81339a4..c9677499a 100644
--- a/controllers/admin/AdminCustomerPreferencesController.php
+++ b/controllers/admin/AdminCustomerPreferencesController.php
@@ -133,7 +133,7 @@ class AdminCustomerPreferencesControllerCore extends AdminController
'PS_KPI_FREQUENT_CUSTOMER_NB_ORDERS' => array(
'title' => $this->l('Number of orders to use to calculate frequent customers'),
'hint' => $this->l('Set the number of orders to use to calculate frequent customers.'),
- 'validation' => 'isUnsignedInt',
+ 'validation' => 'isInt',
'cast' => 'intval',
'type' => 'text',
'class' => 'fixed-width-xxl',
@@ -173,6 +173,14 @@ class AdminCustomerPreferencesControllerCore extends AdminController
);
}
+ public function beforeUpdateOptions()
+ {
+ $fieldData = $this->fields_options['customer_kpi']['fields']['PS_KPI_FREQUENT_CUSTOMER_NB_ORDERS'];
+ if (!Tools::getValue('PS_KPI_FREQUENT_CUSTOMER_NB_ORDERS')) {
+ $this->errors[] = sprintf(Tools::displayError('field %s must be greater than 0.'), $fieldData['title']);;
+ }
+ }
+
/**
* Update PS_B2B_ENABLE and enables / disables the associated tabs
* @param $value integer Value of option
diff --git a/controllers/admin/AdminCustomersController.php b/controllers/admin/AdminCustomersController.php
index 8f4a628ab..f0995a219 100644
--- a/controllers/admin/AdminCustomersController.php
+++ b/controllers/admin/AdminCustomersController.php
@@ -79,6 +79,9 @@ class AdminCustomersControllerCore extends AdminController
$this->_join = 'LEFT JOIN '._DB_PREFIX_.'gender_lang gl ON (a.id_gender = gl.id_gender AND gl.id_lang = '.(int)$this->context->language->id.')';
$this->_join .= ' LEFT JOIN '._DB_PREFIX_.'group_lang grl ON (a.id_default_group = grl.id_group AND grl.id_lang = '.(int)$this->context->language->id.')';
+ $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'orders o ON (a.id_customer = o.id_customer)';
+ $this->_group = 'GROUP BY a.`id_customer`';
+
$this->_use_found_rows = false;
$this->fields_list = array(
'id_customer' => array(
@@ -123,6 +126,7 @@ class AdminCustomersControllerCore extends AdminController
),
'total_orders' => array(
'title' => $this->l('Number of orders'),
+ 'type' => 'range',
'optional' => true,
'visible_default' => true,
'havingFilter' => true,
@@ -163,6 +167,7 @@ class AdminCustomersControllerCore extends AdminController
'date_add' => array(
'title' => $this->l('Registration'),
'type' => 'date',
+ 'filter_key' => 'a!date_add',
'align' => 'text-right'
),
'connect' => array(
@@ -175,6 +180,12 @@ class AdminCustomersControllerCore extends AdminController
'title' => $this->l('Banned'),
'type' => 'bool',
'displayed' => false,
+ ),
+ 'order_date' => array(
+ 'title' => $this->l('Order date'),
+ 'type' => 'date',
+ 'filter_key' => 'o!date_add',
+ 'displayed' => false
)
));
@@ -183,19 +194,8 @@ class AdminCustomersControllerCore extends AdminController
parent::__construct();
$this->_select = '
- a.date_add, gl.name as title, grl.name as default_group_name, (
- SELECT SUM(total_paid_real / conversion_rate)
- FROM '._DB_PREFIX_.'orders o
- WHERE o.id_customer = a.id_customer
- '.Shop::addSqlRestriction(Shop::SHARE_ORDER, 'o').'
- AND o.valid = 1
- ) as total_spent, (
- SELECT COUNT(o.`id_order`)
- FROM '._DB_PREFIX_.'orders o
- WHERE o.id_customer = a.id_customer
- '.Shop::addSqlRestriction(Shop::SHARE_ORDER, 'o').'
- AND o.valid = 1
- ) as total_orders, (
+ a.date_add, gl.name as title, grl.name as default_group_name, COUNT(o.`id_order`) as total_orders,
+ o.`date_add` as order_date, SUM(total_paid_real / conversion_rate) as total_spent, (
SELECT c.date_add FROM '._DB_PREFIX_.'guest g
LEFT JOIN '._DB_PREFIX_.'connections c ON c.id_guest = g.id_guest
WHERE g.id_customer = a.id_customer
@@ -707,7 +707,8 @@ class AdminCustomersControllerCore extends AdminController
$helper->icon = 'icon-star';
$helper->color = 'color2';
$helper->title = $this->l('Total Frequent Customers', null, null, false);
- $helper->subtitle = $this->l('All Time', null, null, false);
+ $helper->subtitle = $this->l('1 year', null, null, false);
+ $helper->href = $this->context->link->getAdminLink('AdminCustomers').'&submitFiltercustomer=1&customerFilter_total_orders%5B0%5D='.Configuration::get('PS_KPI_FREQUENT_CUSTOMER_NB_ORDERS').'&customerFilter_o%21date_add%5B0%5D='.date('Y-m-d', strtotime('-365 day')).'&customerFilter_o%21date_add%5B1%5D='.date('Y-m-d');
$helper->source = $this->context->link->getAdminLink('AdminStats').'&ajax=1&action=getKpi&kpi=total_frequent_customers';
$helper->tooltip = $this->l('The total number of frequent customers in given period of time.', null, null, false);
$kpis[] = $helper;
diff --git a/controllers/admin/AdminOrdersController.php b/controllers/admin/AdminOrdersController.php
index 1af622d3a..9732ed6e2 100644
--- a/controllers/admin/AdminOrdersController.php
+++ b/controllers/admin/AdminOrdersController.php
@@ -2262,6 +2262,88 @@ class AdminOrdersControllerCore extends AdminController
} else {
$this->errors = Tools::displayError('An error occurred while resolving overbooking.');
}
+ // Set old orders address as current order address
+ } elseif (Tools::getValue('action') && Tools::getValue('action') == 'set_old_orders_address') {
+ if ($idOrder = Tools::getValue('id_order')) {
+ if (Validate::isLoadedObject($objOrder = new Order($idOrder))) {
+ $idAddressInvoice = $objOrder->id_address_invoice;
+ if ($idAddressInvoice && Validate::isLoadedObject(new Address($idAddressInvoice))) {
+ // get all customer orders and set old orders address as current order address
+ if ($customerOrders = Order::getCustomerOrders($objOrder->id_customer)) {
+ foreach ($customerOrders as $order) {
+ $objOrder = new Order($order['id_order']);
+ $objOrder->id_address_invoice = $idAddressInvoice;
+ $objOrder->update();
+ }
+ }
+ Tools::redirectAdmin(self::$currentIndex.'&id_order='.$idOrder.'&vieworder&conf=6&token='.$this->token);
+ } else {
+ $this->errors = Tools::displayError('Address not found. Please try again.');
+ }
+ } else {
+ $this->errors = Tools::displayError('Order not found. Please try again.');
+ }
+ } else {
+ $this->errors = Tools::displayError('Order not found. Please try again.');
+ }
+ // Set customer current active address as current order address
+ } elseif (Tools::getValue('action') && Tools::getValue('action') == 'set_address_current_address') {
+ if ($idOrder = Tools::getValue('id_order')) {
+ if (Validate::isLoadedObject($objOrder = new Order($idOrder))) {
+ $idAddressInvoice = $objOrder->id_address_invoice;
+ if ($idAddressInvoice && Validate::isLoadedObject($objOrderAddress = new Address($idAddressInvoice))) {
+ $updateAddress = 1;
+ if ($idCustomerAddress = Customer::getCustomerIdAddress($objOrder->id_customer)) {
+ // only proceed if current active address and current order address are different
+ if ($idCustomerAddress != $idAddressInvoice) {
+ if (Validate::isLoadedObject($objActiveAddress = new Address($idCustomerAddress))) {
+ // set current active address information from order address
+ $objOrderAddress->id = $objOrderAddress->id_address = $objActiveAddress->id;
+ $objOrderAddress->deleted = 0;
+ $objOrderAddress->update();
+ } else {
+ $this->errors = Tools::displayError('Customer address not found. Please try again.');
+ }
+ }
+ } else {
+ // If customer has no active address, create new customer address with the order address
+ $objOrderAddress->id = $objOrderAddress->id_address = null;
+ $objOrderAddress->deleted = 0;
+ $objOrderAddress->add();
+ }
+
+ if (!count($this->errors)) {
+ Tools::redirectAdmin(self::$currentIndex.'&id_order='.$idOrder.'&vieworder&conf=6&token='.$this->token);
+ }
+ } else {
+ $this->errors = Tools::displayError('Address not found. Please try again.');
+ }
+ } else {
+ $this->errors = Tools::displayError('Order not found. Please try again.');
+ }
+ } else {
+ $this->errors = Tools::displayError('Order not found. Please try again.');
+ }
+ } elseif (Tools::getValue('action') && Tools::getValue('action') == 'set_order_active_address') {
+ if ($idOrder = Tools::getValue('id_order')) {
+ if (Validate::isLoadedObject($objOrder = new Order($idOrder))) {
+ // get currenct active address of the customer
+ if ($idCustomerAddress = Customer::getCustomerIdAddress($objOrder->id_customer)) {
+ $objOrder->id_address_invoice = $idCustomerAddress;
+ if ($objOrder->update()) {
+ Tools::redirectAdmin(self::$currentIndex.'&id_order='.$idOrder.'&vieworder&conf=6&token='.$this->token);
+ } else {
+ $this->errors[] = Tools::displayError('Some error occurred while updating address detail. Please try again.');
+ }
+ } else {
+ $this->errors = Tools::displayError('Customer address not found. Please try again.');
+ }
+ } else {
+ $this->errors = Tools::displayError('Order not found. Please try again.');
+ }
+ } else {
+ $this->errors = Tools::displayError('Order not found. Please try again.');
+ }
}
// Sending loader image for the modals to be used for all the modals ajax processes
@@ -2838,7 +2920,27 @@ class AdminOrdersControllerCore extends AdminController
// Overbookings information of the order
$orderOverBookings = $objHotelBookingDetail->getOverbookedRooms($order->id, 0, '', '', 0, 0, 1);
+ // Guest address info
+ $guestFormattedAddress = '';
+ $idOrderAddressInvoice = 0;
+ $ordersWithDiffInvAddr = 0;
+ $idCurrentAddress = Customer::getCustomerIdAddress($order->id_customer);
+ if ($order->id_address_invoice && Validate::isLoadedObject($objGuestAddress = new Address($order->id_address_invoice))) {
+ $idOrderAddressInvoice = $order->id_address_invoice;
+ $guestFormattedAddress = AddressFormat::generateAddress($objGuestAddress, array(), "
");
+
+ // get customer orders without same id_address_invoice
+ if ($customerOrders = Order::getCustomerOrders($order->id_customer, false, null, $idOrderAddressInvoice, 1)) {
+ if ($customerOrders > 1) {
+ $ordersWithDiffInvAddr = 1;
+ }
+ }
+ }
$this->tpl_view_vars = array(
+ 'guestFormattedAddress' => $guestFormattedAddress,
+ 'idOrderAddressInvoice' => $idOrderAddressInvoice,
+ 'ordersWithDiffInvAddr' => $ordersWithDiffInvAddr,
+ 'idCurrentAddress' => $idCurrentAddress,
'totalRefundedRooms' => $totalRefundedRooms,
'orderOverBookings' => $orderOverBookings,
// refund info
@@ -6186,6 +6288,14 @@ class AdminOrdersControllerCore extends AdminController
$res &= $objOrderDetail->update();
}
+ if ($objOrderDetail->id_order_invoice != 0) {
+ // values changes as values are calculated
+ $objOrderInvoice = new OrderInvoice($objOrderDetail->id_order_invoice);
+ $objOrderInvoice->total_paid_tax_excl -= $priceTaxExcl;
+ $objOrderInvoice->total_paid_tax_incl -= $priceTaxIncl;
+ $res &= $objOrderInvoice->update();
+ }
+
$order->total_paid_tax_excl -= $priceTaxExcl;
$order->total_paid_tax_incl -= $priceTaxIncl;
$order->total_paid -= $priceTaxIncl;
@@ -6219,6 +6329,9 @@ class AdminOrdersControllerCore extends AdminController
// valiadate services being added
if (Validate::isLoadedObject($objHotelBookingDetail = new HotelBookingDetail($idBookingDetail))) {
$objOrder = new Order($objHotelBookingDetail->id_order);
+ $objOrderDetail = new OrderDetail($objHotelBookingDetail->id_order_detail);
+ $objOrderInvoice = new OrderInvoice($objOrderDetail->id_order_invoice);
+
// set context currency So that we can get prices in the order currency
$this->context->currency = new Currency($objOrder->id_currency);
@@ -6400,7 +6513,7 @@ class AdminOrdersControllerCore extends AdminController
}
$order_detail = new OrderDetail();
- $order_detail->createList($order, $cart, $order->getCurrentOrderState(), $productList, (isset($order_invoice) ? $order_invoice->id : 0), true);
+ $order_detail->createList($order, $cart, $order->getCurrentOrderState(), $productList, (isset($objOrderInvoice) ? $objOrderInvoice->id : 0), true);
$objRoomTypeServiceProductOrderDetail = new RoomTypeServiceProductOrderDetail();
$objRoomTypeServiceProductOrderDetail->id_product = $product['id_product'];
@@ -6424,16 +6537,18 @@ class AdminOrdersControllerCore extends AdminController
$order->total_paid_tax_excl += Tools::ps_round((float)($totalPriceChangeTaxExcl), 2);
$order->total_paid_tax_incl += Tools::ps_round((float)($totalPriceChangeTaxIncl), 2);
- if (isset($order_invoice) && Validate::isLoadedObject($order_invoice)) {
- $order->total_shipping = $order_invoice->total_shipping_tax_incl;
- $order->total_shipping_tax_incl = $order_invoice->total_shipping_tax_incl;
- $order->total_shipping_tax_excl = $order_invoice->total_shipping_tax_excl;
+ // update invoice total
+ if (isset($objOrderInvoice) && Validate::isLoadedObject($objOrderInvoice)) {
+ $objOrderInvoice->total_paid_tax_excl += Tools::ps_round((float)($totalPriceChangeTaxExcl), 2);
+ $objOrderInvoice->total_paid_tax_incl += Tools::ps_round((float)($totalPriceChangeTaxIncl), 2);
+ $objOrderInvoice->save();
}
// discount
$order->total_discounts += (float)abs($cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS));
$order->total_discounts_tax_excl += (float)abs($cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS));
$order->total_discounts_tax_incl += (float)abs($cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS));
+
// Save changes of order
$order->update();
if (Validate::isLoadedObject($specific_price)) {
@@ -6634,8 +6749,9 @@ class AdminOrdersControllerCore extends AdminController
$order_invoice = new OrderInvoice($order_detail->id_order_invoice);
$order_invoice->total_paid_tax_excl += $priceDiffTaxExcl;
$order_invoice->total_paid_tax_incl += $priceDiffTaxIncl;
- $res &= $order_invoice->update();
+ $order_invoice->update();
}
+
$order = new Order($objBookingDetail->id_order);
$order->total_paid_tax_excl += $priceDiffTaxExcl;
$order->total_paid_tax_incl += $priceDiffTaxIncl;
diff --git a/controllers/admin/AdminStatsController.php b/controllers/admin/AdminStatsController.php
index b2ef1e69b..2a4e6666e 100644
--- a/controllers/admin/AdminStatsController.php
+++ b/controllers/admin/AdminStatsController.php
@@ -910,7 +910,12 @@ class AdminStatsControllerCore extends AdminStatsTabController
case 'total_frequent_customers':
$nbOrdersFrequentCustomers = Configuration::get('PS_KPI_FREQUENT_CUSTOMER_NB_ORDERS');
- $value = AdminStatsController::getTotalFrequentCustomers($nbOrdersFrequentCustomers, 0);
+ $value = AdminStatsController::getTotalFrequentCustomers(
+ date('Y-m-d', strtotime('-365 day')),
+ date('Y-m-d'),
+ $nbOrdersFrequentCustomers,
+ 0
+ );
break;
@@ -1829,7 +1834,7 @@ class AdminStatsControllerCore extends AdminStatsTabController
return $result;
}
- public static function getTotalFrequentCustomers($nbOrders = 5, $idHotel = null)
+ public static function getTotalFrequentCustomers($dateFrom, $dateTo, $nbOrders = 5, $idHotel = null)
{
$sql = 'SELECT COUNT(t.`id_customer`)
FROM (
@@ -1840,7 +1845,7 @@ class AdminStatsControllerCore extends AdminStatsTabController
WHERE hbd.`id_order` = o.`id_order` LIMIT 1
) AS id_hotel
FROM `'._DB_PREFIX_.'orders` o
- WHERE o.`valid` = 1
+ WHERE o.`valid` = 1 AND o.`date_add` BETWEEN "'.pSQL($dateFrom).' 00:00:00" AND "'.pSQL($dateTo).' 23:59:59"
GROUP BY o.`id_customer`
HAVING 1 '.(!is_null($idHotel) ? HotelBranchInformation::addHotelRestriction($idHotel) : '').'
) AS t
diff --git a/controllers/front/GuestTrackingController.php b/controllers/front/GuestTrackingController.php
index 79ec067c2..f43014df8 100644
--- a/controllers/front/GuestTrackingController.php
+++ b/controllers/front/GuestTrackingController.php
@@ -250,6 +250,9 @@ class GuestTrackingControllerCore extends FrontController
$total_convenience_fee_te = 0;
$total_convenience_fee_ti = 0;
+ $objOrderReturn = new OrderReturn();
+ $refundReqBookings = $objOrderReturn->getOrderRefundRequestedBookings($order->id, 0, 1);
+
foreach ($orderProducts as $type_key => $type_value) {
if (in_array($type_value['product_id'], $processedProducts)) {
continue;
@@ -307,6 +310,14 @@ class GuestTrackingControllerCore extends FrontController
if ($data_v['is_back_order']) {
$anyBackOrder = 1;
}
+
+ if ($refundReqBookings && in_array($data_v['id'], $refundReqBookings) && $data_v['is_refunded']) {
+ if ($data_v['is_cancelled']) {
+ $cartHotelData[$type_key]['date_diff'][$date_join]['count_cancelled'] += 1;
+ } else {
+ $cartHotelData[$type_key]['date_diff'][$date_join]['count_refunded'] += 1;
+ }
+ }
} else {
$num_days = $objBookingDetail->getNumberOfDays($data_v['date_from'], $data_v['date_to']);
$cartHotelData[$type_key]['date_diff'][$date_join]['num_rm'] = 1;
@@ -326,6 +337,16 @@ class GuestTrackingControllerCore extends FrontController
if ($data_v['is_back_order']) {
$anyBackOrder = 1;
}
+
+ $cartHotelData[$type_key]['date_diff'][$date_join]['count_cancelled'] = 0;
+ $cartHotelData[$type_key]['date_diff'][$date_join]['count_refunded'] = 0;
+ if ($refundReqBookings && in_array($data_v['id'], $refundReqBookings) && $data_v['is_refunded']) {
+ if ($data_v['is_cancelled']) {
+ $cartHotelData[$type_key]['date_diff'][$date_join]['count_cancelled'] += 1;
+ } else {
+ $cartHotelData[$type_key]['date_diff'][$date_join]['count_refunded'] += 1;
+ }
+ }
}
$cartHotelData[$type_key]['date_diff'][$date_join]['is_refunded'] = $data_v['is_refunded'];
@@ -583,6 +604,7 @@ class GuestTrackingControllerCore extends FrontController
'CUSTOMIZE_TEXTFIELD' => Product::CUSTOMIZE_TEXTFIELD,
'use_tax' => Configuration::get('PS_TAX'),
'guestInformations' => (array)$customer,
+ 'view_on_map' => Configuration::get('WK_GOOGLE_ACTIVE_MAP'),
));
}
@@ -627,6 +649,7 @@ class GuestTrackingControllerCore extends FrontController
'map_input_text' => $objHotelBranchInformation->map_input_text,
),
'hotel_name' => $objHotelBranchInformation->hotel_name,
+ 'PS_STORES_ICON' => $this->context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_STORES_ICON'))
));
$this->addJS(
diff --git a/js/admin/orders.js b/js/admin/orders.js
index e34779f26..947288ee2 100644
--- a/js/admin/orders.js
+++ b/js/admin/orders.js
@@ -1249,7 +1249,23 @@ function setRoomTypeGuestOccupancy(booking_occupancy_wrapper)
/* Refund system script */
var flagRefund = '';
+// when submit from ajax from guest address controller the function will be called from the controller header
+function getSummary()
+{
+ return;
+}
+
$(document).ready(function() {
+ // when click edit/add guest address we have to initialize fancybox
+ $('.fancybox').fancybox({
+ 'type': 'iframe',
+ 'width': '90%',
+ 'height': '90%',
+ afterClose: function() {
+ location.reload();
+ },
+ });
+
// when change order state to cancel or refund then show modal of bookings cancellation
$(document).on('change', '#id_order_state', function(e) {
if ($(this).val() == PS_OS_CANCELED || $(this).val() == PS_OS_REFUND) {
diff --git a/modules/hotelreservationsystem/classes/HotelBookingDemands.php b/modules/hotelreservationsystem/classes/HotelBookingDemands.php
index a018e952a..57904d0a4 100644
--- a/modules/hotelreservationsystem/classes/HotelBookingDemands.php
+++ b/modules/hotelreservationsystem/classes/HotelBookingDemands.php
@@ -75,6 +75,7 @@ class HotelBookingDemands extends ObjectModel
$groupByRoom = 1,
$getTotalPrice = 0,
$useTax = 1,
+ $idOrderDetail = 0,
$idHtlBookingDetail = 0
) {
$moduleObj = Module::getInstanceByName('hotelreservationsystem');
@@ -91,6 +92,10 @@ class HotelBookingDemands extends ObjectModel
LEFT JOIN `'._DB_PREFIX_.'htl_booking_detail` hb ON (hd.`id_htl_booking` = hb.`id`)
WHERE hb.`id_order` ='.(int) $idOrder;
+
+ if ($idOrderDetail) {
+ $sql .= ' AND `id_order_detail`='.(int)$idOrderDetail;
+ }
if ($idProduct) {
$sql .= ' AND hb.`id_product`='.(int)$idProduct;
}
@@ -251,16 +256,21 @@ class HotelBookingDemands extends ObjectModel
|| Configuration::get('PS_INVOICE_TAXES_BREAKDOWN');
}
- public function getExtraDemandsTaxesDetails($idOrder)
+ public function getExtraDemandsTaxesDetails($idOrder, $idsOrderDetail = [])
{
- $taxDetails = Db::getInstance()->executeS(
- 'SELECT hb.`id` as id_htl_booking, hbd.`unit_price_tax_excl`, hbd.`total_price_tax_excl`, hb.`id_order_detail`, hdt.*, t.* FROM '._DB_PREFIX_.'orders o '.
- 'INNER JOIN '._DB_PREFIX_.'htl_booking_detail hb ON hb.id_order = o.id_order '.
- 'INNER JOIN '._DB_PREFIX_.'htl_booking_demands hbd ON hbd.id_htl_booking = hb.id '.
- 'INNER JOIN '._DB_PREFIX_.'htl_booking_demands_tax hdt ON hbd.id_booking_demand = hdt.id_booking_demand '.
- 'INNER JOIN '._DB_PREFIX_.'tax t ON t.id_tax = hdt.id_tax '.
- 'WHERE o.id_order = '.(int)$idOrder
- );
+ $sql = 'SELECT hb.`id` as id_htl_booking, hbd.`unit_price_tax_excl`, hbd.`total_price_tax_excl`, hb.`id_order_detail`, hdt.*, t.* FROM '._DB_PREFIX_.'orders o '.
+ 'INNER JOIN '._DB_PREFIX_.'htl_booking_detail hb ON hb.id_order = o.id_order '.
+ 'INNER JOIN '._DB_PREFIX_.'htl_booking_demands hbd ON hbd.id_htl_booking = hb.id '.
+ 'INNER JOIN '._DB_PREFIX_.'htl_booking_demands_tax hdt ON hbd.id_booking_demand = hdt.id_booking_demand '.
+ 'INNER JOIN '._DB_PREFIX_.'tax t ON t.id_tax = hdt.id_tax '.
+ 'WHERE o.id_order = '.(int)$idOrder;
+
+ if ($idsOrderDetail) {
+ $sql .= ' AND hb.`id_order_detail` IN ('.implode(',', $idsOrderDetail).')';
+ }
+
+ $taxDetails = Db::getInstance()->executeS($sql);
+
if ($taxDetails) {
foreach ($taxDetails as &$detail) {
$priceTaxExcl = $detail['unit_price_tax_excl'];
diff --git a/modules/hotelreservationsystem/classes/HotelBookingDetail.php b/modules/hotelreservationsystem/classes/HotelBookingDetail.php
index 99b23f553..2cf3dac59 100644
--- a/modules/hotelreservationsystem/classes/HotelBookingDetail.php
+++ b/modules/hotelreservationsystem/classes/HotelBookingDetail.php
@@ -2545,13 +2545,17 @@ class HotelBookingDetail extends ObjectModel
* @param int $id_customer [description]
* @return [type] [description]
*/
- public function getOnlyOrderBookingData($id_order, $id_guest, $id_product, $id_customer = 0)
+ public function getOnlyOrderBookingData($id_order, $id_guest, $id_product, $id_customer = 0, $id_order_detail = 0)
{
$sql = 'SELECT hbd.*, od.`unit_price_tax_incl`, od.`unit_price_tax_excl`, od.`reduction_amount_tax_excl`,
od.`reduction_amount_tax_incl` FROM `'._DB_PREFIX_.'htl_booking_detail` hbd
INNER JOIN `'._DB_PREFIX_.'order_detail` od ON (od.`id_order_detail` = hbd.`id_order_detail`)
WHERE hbd.`id_order` = '.(int)$id_order.' AND hbd.`id_product` = '.(int)$id_product;
+ if ($id_order_detail) {
+ $sql .= ' AND hbd.`id_order_detail` = '.(int)$id_order_detail;
+ }
+
if ($id_customer) {
$sql .= ' AND hbd.`id_customer` = '.(int)$id_customer;
}
diff --git a/modules/hotelreservationsystem/classes/RoomTypeServiceProductOrderDetail.php b/modules/hotelreservationsystem/classes/RoomTypeServiceProductOrderDetail.php
index 278c7dfa9..f7e4bc2c0 100644
--- a/modules/hotelreservationsystem/classes/RoomTypeServiceProductOrderDetail.php
+++ b/modules/hotelreservationsystem/classes/RoomTypeServiceProductOrderDetail.php
@@ -68,7 +68,8 @@ class RoomTypeServiceProductOrderDetail extends ObjectModel
$getTotalPrice = 0,
$useTax = null,
$autoAddToCart = 0,
- $priceAdditionType = null
+ $priceAdditionType = null,
+ $idOrderDetail = 0
) {
if ($useTax === null) {
@@ -85,6 +86,10 @@ class RoomTypeServiceProductOrderDetail extends ObjectModel
$sql .= ' LEFT JOIN `'._DB_PREFIX_.'order_detail` od ON(od.`id_order_detail` = rsod.`id_order_detail`)';
$sql .= ' WHERE rsod.`id_order` = '.(int)$idOrder;
+ if ($idOrderDetail) {
+ $sql .= ' AND rsod.`id_order_detail` = '.(int)$idOrderDetail;
+ }
+
if (!is_null($autoAddToCart)) {
$sql .= ' AND od.`product_auto_add` = '. (int)$autoAddToCart;
if ($autoAddToCart == 1 && !is_null($priceAdditionType)) {
diff --git a/modules/hotelreservationsystem/classes/WebserviceSpecificManagementHotelAri.php b/modules/hotelreservationsystem/classes/WebserviceSpecificManagementHotelAri.php
index bfdbfdce8..bc4b33dce 100644
--- a/modules/hotelreservationsystem/classes/WebserviceSpecificManagementHotelAri.php
+++ b/modules/hotelreservationsystem/classes/WebserviceSpecificManagementHotelAri.php
@@ -29,7 +29,7 @@ class WebserviceSpecificManagementHotelAri extends ObjectModel implements Webser
public $get_booked_rooms;
public $get_partial_available_rooms;
public $get_unavailable_rooms;
-
+ public $date_wise_breakdown;
/** @var WebserviceOutputBuilder */
protected $objOutput;
@@ -51,6 +51,7 @@ class WebserviceSpecificManagementHotelAri extends ObjectModel implements Webser
'get_booked_rooms' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
'get_partial_available_rooms' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
'get_unavailable_rooms' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
+ 'date_wise_breakdown' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
),
);
@@ -225,21 +226,59 @@ class WebserviceSpecificManagementHotelAri extends ObjectModel implements Webser
}
// now call the function
- $obBookingDtl = new HotelBookingDetail();
- $ariInfo = $obBookingDtl->getBookingData($bookingParams);
+ $objBookingDtl = new HotelBookingDetail();
- // append request fields also. will be attached in the response xml
- $ariInfo['id_hotel'] = $ariParams['id_hotel'];
- $ariInfo['date_from'] = $bookingParams['date_from'];
- $ariInfo['date_to'] = $bookingParams['date_to'];
- $ariInfo['num_rooms'] = $totalRooms;
+ $searchAriData = [];
+
+ // If api is called for getting ari info for all the dates in the provided date range
+ if (isset($ariParams['date_wise_breakdown']) && $ariParams['date_wise_breakdown'] && $bookingParams['search_available']) {
+ $dateWiseBreakdown = 1;
+
+ $datesAriInfo = [];
+
+ $dateFrom = $bookingParams['date_from'];
+ $dateTo = $bookingParams['date_to'];
+
+ // Lets get data date by date (Every date in the date range)
+ $dateBookingParams = $bookingParams;
+ // for a single date there is no use of partial available rooms
+ $dateBookingParams['search_partial'] = 0;
+
+ for ($currentDate = $dateFrom; $currentDate < $dateTo; $currentDate = date('Y-m-d', strtotime('+1 day', strtotime($currentDate)))) {
+ $dateBookingParams['date_from'] = $currentDate;
+ $dateBookingParams['date_to'] = date('Y-m-d', strtotime('+1 day', strtotime($currentDate)));
+
+ // get inventories for every date
+ $ariInfo = $objBookingDtl->getBookingData($dateBookingParams);
+ // append request fields also. will be attached in the response xml
+ $ariInfo['id_hotel'] = $ariParams['id_hotel'];
+ $ariInfo['date_from'] = $dateBookingParams['date_from'];
+ $ariInfo['date_to'] = $dateBookingParams['date_to'];
+ $ariInfo['num_rooms'] = $totalRooms;
+
+ $searchAriData[] = $ariInfo;
+ }
+ } else { // If api is called for getting ari info for a particular date range
+ $dateWiseBreakdown = 0;
+
+ // If api is called for getting ari info for a particular date range
+ $ariInfo = $objBookingDtl->getBookingData($bookingParams);
+
+ // append request fields also. will be attached in the response xml
+ $ariInfo['id_hotel'] = $ariParams['id_hotel'];
+ $ariInfo['date_from'] = $bookingParams['date_from'];
+ $ariInfo['date_to'] = $bookingParams['date_to'];
+ $ariInfo['num_rooms'] = $totalRooms;
+
+ $searchAriData[] = $ariInfo;
+ }
// We have to create the json and xml response for request by ourself. So we need to check if data to be sent in xml or json
// We have no way to check the output format from parent classed. So we used below code
if (get_class($this->objOutput->getObjectRender()) == 'WebserviceOutputJSON') {
- $this->getResponseJson($ariInfo);
+ $this->getResponseJson($searchAriData, $dateWiseBreakdown);
} else {
- $this->getResponseXml($ariInfo);
+ $this->getResponseXml($searchAriData, $dateWiseBreakdown);
}
}
@@ -392,167 +431,180 @@ class WebserviceSpecificManagementHotelAri extends ObjectModel implements Webser
}
// create xml for the response of the ari request
- private function getResponseXml($ariInfo)
+ private function getResponseXml($ariInfoArray, $dateWiseBreakdown = 0)
{
- $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('hotel_ari', array());
-
- $field = array('sqlId' => 'id_hotel', 'value' => $ariInfo['id_hotel'], 'xlink_resource' => 'hotels');
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
-
- $field = array('sqlId' => 'date_from', 'value' => $ariInfo['date_from']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
-
- $field = array('sqlId' => 'date_to', 'value' => $ariInfo['date_to']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
-
- $objCurrency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
- $field = array('sqlId' => 'currency', 'value' => $objCurrency->iso_code);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
-
- // check if availability stats are available then only process further
- if (isset($ariInfo['stats']) && $ariInfo['stats']) {
- $field = array('sqlId' => 'total_rooms', 'value' => $ariInfo['stats']['total_rooms']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
-
- if (isset($ariInfo['stats']['num_avail'])) {
- $field = array('sqlId' => 'total_available_rooms', 'value' => $ariInfo['stats']['num_avail']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+ if ($ariInfoArray) {
+ // if date wise breakup is requested the parent node will be 'hotel_aris' as per other APIs in QloApps (orders > order)
+ if ($dateWiseBreakdown) {
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('hotel_aris', array());
}
+ foreach ($ariInfoArray as $ariInfo) {
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('hotel_ari', array());
- if (isset($ariInfo['stats']['num_unavail'])) {
- $field = array('sqlId' => 'total_unavailable_rooms', 'value' => $ariInfo['stats']['num_unavail']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
- }
-
- if (isset($ariInfo['stats']['num_part_avai'])) {
- $field = array('sqlId' => 'total_partial_available_rooms', 'value' => $ariInfo['stats']['num_part_avai']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
- }
-
- if (isset($ariInfo['stats']['num_booked'])) {
- $field = array('sqlId' => 'total_booked_rooms', 'value' => $ariInfo['stats']['num_booked']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
- }
- }
-
- // check if room type data is available then only process further
- if (isset($ariInfo['rm_data']) && $ariInfo['rm_data']) {
- $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('room_types', array());
-
- foreach ($ariInfo['rm_data'] as $roomTypeInfo) {
- $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('room_type', array(), array('id' => $roomTypeInfo['id_product'], 'xlink_resource' => $this->wsObject->wsUrl.'room_types'.'/'.$roomTypeInfo['id_product']));
-
- $field = array('sqlId' => 'id_room_type', 'value' => $roomTypeInfo['id_product'], 'xlink_resource' => 'room_types');
+ $field = array('sqlId' => 'id_hotel', 'value' => $ariInfo['id_hotel'], 'xlink_resource' => 'hotels');
$this->output .= $this->objOutput->getObjectRender()->renderField($field);
- // get feature price of room type
- $roomTypePrice = HotelRoomTypeFeaturePricing::getRoomTypeFeaturePricesPerDay(
- $roomTypeInfo['id_product'],
- $ariInfo['date_from'],
- $ariInfo['date_to'],
- 0
- );
- $field = array('sqlId' => 'base_price', 'value' => $roomTypePrice);
+ $field = array('sqlId' => 'date_from', 'value' => $ariInfo['date_from']);
$this->output .= $this->objOutput->getObjectRender()->renderField($field);
- // get feature price of room type
- $roomTypePrice = HotelRoomTypeFeaturePricing::getRoomTypeFeaturePricesPerDay(
- $roomTypeInfo['id_product'],
- $ariInfo['date_from'],
- $ariInfo['date_to'],
- 1
- );
- $field = array('sqlId' => 'base_price_with_tax', 'value' => $roomTypePrice);
+ $field = array('sqlId' => 'date_to', 'value' => $ariInfo['date_to']);
$this->output .= $this->objOutput->getObjectRender()->renderField($field);
- $totalBookingPrice = HotelRoomTypeFeaturePricing::getRoomTypeTotalPrice(
- $roomTypeInfo['id_product'],
- $ariInfo['date_from'],
- $ariInfo['date_to'],
- $ariInfo['num_rooms']
- );
- $field = array('sqlId' => 'total_price', 'value' => $totalBookingPrice['total_price_tax_excl']);
+ $objCurrency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
+ $field = array('sqlId' => 'currency', 'value' => $objCurrency->iso_code);
$this->output .= $this->objOutput->getObjectRender()->renderField($field);
- $totalBookingPrice = HotelRoomTypeFeaturePricing::getRoomTypeTotalPrice(
- $roomTypeInfo['id_product'],
- $ariInfo['date_from'],
- $ariInfo['date_to'],
- $ariInfo['num_rooms']
- );
- $field = array('sqlId' => 'total_price_with_tax', 'value' => $totalBookingPrice['total_price_tax_incl']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+ // check if availability stats are available then only process further
+ if (isset($ariInfo['stats']) && $ariInfo['stats']) {
+ $field = array('sqlId' => 'total_rooms', 'value' => $ariInfo['stats']['total_rooms']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
- $objRoomType = new Product($roomTypeInfo['id_product']);
- $field = array('sqlId' => 'name', 'value' => $objRoomType->name, 'i18n' => true);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
-
- // rooms info of the room type
- if (isset($roomTypeInfo['data']) && $roomTypeInfo['data']) {
- $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('rooms', array());
- foreach ($roomTypeInfo['data'] as $key => $roomsInfo) {
- if ($key == 'available') {
- $nodeRoomAvailability = 'available';
- } elseif ($key == 'unavailable') {
- $nodeRoomAvailability = 'unavailable';
- } elseif ($key == 'booked') {
- $nodeRoomAvailability = 'booked';
- } elseif ($key == 'partially_available') {
- $nodeRoomAvailability = 'partial_available';
- }
-
- $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($nodeRoomAvailability, array());
- if ($key == 'partially_available') {
- foreach ($roomsInfo as $dateIndex => $partialRoomsInfo) {
- if (isset($partialRoomsInfo['rooms']) && $partialRoomsInfo['rooms']) {
- $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('rooms', array(), array('date_from' => $partialRoomsInfo['date_from'], 'date_to' => $partialRoomsInfo['date_to']));
-
- foreach ($partialRoomsInfo['rooms'] as $roomInfo) {
- $roomDetail = array();
- $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('room', array(), array('id' => $roomInfo['id_room']));
-
- $field = array('sqlId' => 'id_room', 'value' => $roomInfo['id_room']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
-
- $field = array('sqlId' => 'room_number', 'value' => $roomInfo['room_num']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
-
- $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('room', array());
- }
-
- $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('rooms', array());
- }
- }
- } else {
- if ($roomsInfo) {
- foreach ($roomsInfo as $roomInfo) {
- $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('room', array(), array('id' => $roomInfo['id_room']));
-
- $field = array('sqlId' => 'id_room', 'value' => $roomInfo['id_room']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
-
- $field = array('sqlId' => 'room_number', 'value' => $roomInfo['room_num']);
- $this->output .= $this->objOutput->getObjectRender()->renderField($field);
-
- $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('room', array());
- }
- }
- }
-
- $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter($nodeRoomAvailability, array());
+ if (isset($ariInfo['stats']['num_avail'])) {
+ $field = array('sqlId' => 'total_available_rooms', 'value' => $ariInfo['stats']['num_avail']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
}
- $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('rooms', array());
+ if (isset($ariInfo['stats']['num_unavail'])) {
+ $field = array('sqlId' => 'total_unavailable_rooms', 'value' => $ariInfo['stats']['num_unavail']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+ }
+
+ if (isset($ariInfo['stats']['num_part_avai'])) {
+ $field = array('sqlId' => 'total_partial_available_rooms', 'value' => $ariInfo['stats']['num_part_avai']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+ }
+
+ if (isset($ariInfo['stats']['num_booked'])) {
+ $field = array('sqlId' => 'total_booked_rooms', 'value' => $ariInfo['stats']['num_booked']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+ }
}
- $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('room_type', array());
+ // check if room type data is available then only process further
+ if (isset($ariInfo['rm_data']) && $ariInfo['rm_data']) {
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('room_types', array());
+
+ foreach ($ariInfo['rm_data'] as $roomTypeInfo) {
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('room_type', array(), array('id' => $roomTypeInfo['id_product'], 'xlink_resource' => $this->wsObject->wsUrl.'room_types'.'/'.$roomTypeInfo['id_product']));
+
+ $field = array('sqlId' => 'id_room_type', 'value' => $roomTypeInfo['id_product'], 'xlink_resource' => 'room_types');
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+
+ // get feature price of room type
+ $roomTypePrice = HotelRoomTypeFeaturePricing::getRoomTypeFeaturePricesPerDay(
+ $roomTypeInfo['id_product'],
+ $ariInfo['date_from'],
+ $ariInfo['date_to'],
+ 0
+ );
+ $field = array('sqlId' => 'base_price', 'value' => $roomTypePrice);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+
+ // get feature price of room type
+ $roomTypePrice = HotelRoomTypeFeaturePricing::getRoomTypeFeaturePricesPerDay(
+ $roomTypeInfo['id_product'],
+ $ariInfo['date_from'],
+ $ariInfo['date_to'],
+ 1
+ );
+ $field = array('sqlId' => 'base_price_with_tax', 'value' => $roomTypePrice);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+
+ $totalBookingPrice = HotelRoomTypeFeaturePricing::getRoomTypeTotalPrice(
+ $roomTypeInfo['id_product'],
+ $ariInfo['date_from'],
+ $ariInfo['date_to'],
+ $ariInfo['num_rooms']
+ );
+ $field = array('sqlId' => 'total_price', 'value' => $totalBookingPrice['total_price_tax_excl']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+
+ $totalBookingPrice = HotelRoomTypeFeaturePricing::getRoomTypeTotalPrice(
+ $roomTypeInfo['id_product'],
+ $ariInfo['date_from'],
+ $ariInfo['date_to'],
+ $ariInfo['num_rooms']
+ );
+ $field = array('sqlId' => 'total_price_with_tax', 'value' => $totalBookingPrice['total_price_tax_incl']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+
+ $objRoomType = new Product($roomTypeInfo['id_product']);
+ $field = array('sqlId' => 'name', 'value' => $objRoomType->name, 'i18n' => true);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+
+ // rooms info of the room type
+ if (isset($roomTypeInfo['data']) && $roomTypeInfo['data']) {
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('rooms', array());
+ foreach ($roomTypeInfo['data'] as $key => $roomsInfo) {
+ if ($key == 'available') {
+ $nodeRoomAvailability = 'available';
+ } elseif ($key == 'unavailable') {
+ $nodeRoomAvailability = 'unavailable';
+ } elseif ($key == 'booked') {
+ $nodeRoomAvailability = 'booked';
+ } elseif ($key == 'partially_available') {
+ $nodeRoomAvailability = 'partial_available';
+ }
+
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($nodeRoomAvailability, array());
+ if ($key == 'partially_available') {
+ foreach ($roomsInfo as $dateIndex => $partialRoomsInfo) {
+ if (isset($partialRoomsInfo['rooms']) && $partialRoomsInfo['rooms']) {
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('rooms', array(), array('date_from' => $partialRoomsInfo['date_from'], 'date_to' => $partialRoomsInfo['date_to']));
+
+ foreach ($partialRoomsInfo['rooms'] as $roomInfo) {
+ $roomDetail = array();
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('room', array(), array('id' => $roomInfo['id_room']));
+
+ $field = array('sqlId' => 'id_room', 'value' => $roomInfo['id_room']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+
+ $field = array('sqlId' => 'room_number', 'value' => $roomInfo['room_num']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('room', array());
+ }
+
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('rooms', array());
+ }
+ }
+ } else {
+ if ($roomsInfo) {
+ foreach ($roomsInfo as $roomInfo) {
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('room', array(), array('id' => $roomInfo['id_room']));
+
+ $field = array('sqlId' => 'id_room', 'value' => $roomInfo['id_room']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+
+ $field = array('sqlId' => 'room_number', 'value' => $roomInfo['room_num']);
+ $this->output .= $this->objOutput->getObjectRender()->renderField($field);
+
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('room', array());
+ }
+ }
+ }
+
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter($nodeRoomAvailability, array());
+ }
+
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('rooms', array());
+ }
+
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('room_type', array());
+ }
+
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('room_types', array());
+ }
+
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('hotel_ari', array());
}
- $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('room_types', array());
+ // if date wise breakup is requested the parent node will be 'hotel_aris' as per other APIs in QloApps (orders > order)
+ if ($dateWiseBreakdown) {
+ $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('hotel_aris', array());
+ }
}
- $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('hotel_ari', array());
-
// wrap with the common parent header of QloApps xml api responses
$this->output = $this->objOutput->getObjectRender()->overrideContent($this->output);
@@ -560,131 +612,146 @@ class WebserviceSpecificManagementHotelAri extends ObjectModel implements Webser
}
// create json for the response of the ari request
- private function getResponseJson($ariInfo)
+ private function getResponseJson($ariInfoArray, $dateWiseBreakdown = 0)
{
$ariFormatted = array();
- $ariFormatted['hotel_ari'] = array();
- $ariFormatted['hotel_ari']['id_hotel'] = $ariInfo['id_hotel'];
- $ariFormatted['hotel_ari']['date_from'] = $ariInfo['date_from'];
- $ariFormatted['hotel_ari']['date_to'] = $ariInfo['date_to'];
+ if ($ariInfoArray) {
+ foreach ($ariInfoArray as $ariInfo) {
+ $dateAriInfo = array();
+ $dateAriInfo = array();
+ $dateAriInfo['id_hotel'] = $ariInfo['id_hotel'];
+ $dateAriInfo['date_from'] = $ariInfo['date_from'];
+ $dateAriInfo['date_to'] = $ariInfo['date_to'];
- $objCurrency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
- $ariFormatted['hotel_ari']['currency'] = $objCurrency->iso_code;
+ $objCurrency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
+ $dateAriInfo['currency'] = $objCurrency->iso_code;
- // check if availability stats are available then only process further
- if (isset($ariInfo['stats']) && $ariInfo['stats']) {
- $ariFormatted['hotel_ari']['total_rooms'] = $ariInfo['stats']['total_rooms'];
- if (isset($ariInfo['stats']['num_avail'])) {
- $ariFormatted['hotel_ari']['total_available_rooms'] = $ariInfo['stats']['num_avail'];
- }
- if (isset($ariInfo['stats']['num_unavail'])) {
- $ariFormatted['hotel_ari']['total_unavailable_rooms'] = $ariInfo['stats']['num_unavail'];
- }
- if (isset($ariInfo['stats']['num_part_avai'])) {
- $ariFormatted['hotel_ari']['total_partial_available_rooms'] = $ariInfo['stats']['num_part_avai'];
- }
- if (isset($ariInfo['stats']['num_booked'])) {
- $ariFormatted['hotel_ari']['total_booked_rooms'] = $ariInfo['stats']['num_booked'];
- }
- }
-
- // check if room type data is available then only process further
- if (isset($ariInfo['rm_data']) && $ariInfo['rm_data']) {
- $ariFormatted['hotel_ari']['room_types'] = array();
-
- foreach ($ariInfo['rm_data'] as $roomTypeIndex => $roomTypeInfo) {
- // get feature price of room type
- $roomTypePriceTE = HotelRoomTypeFeaturePricing::getRoomTypeFeaturePricesPerDay(
- $roomTypeInfo['id_product'],
- $ariInfo['date_from'],
- $ariInfo['date_to'],
- 0
- );
- $roomTypePriceTI = HotelRoomTypeFeaturePricing::getRoomTypeFeaturePricesPerDay(
- $roomTypeInfo['id_product'],
- $ariInfo['date_from'],
- $ariInfo['date_to'],
- 1
- );
- $totalBookingPrice = HotelRoomTypeFeaturePricing::getRoomTypeTotalPrice(
- $roomTypeInfo['id_product'],
- $ariInfo['date_from'],
- $ariInfo['date_to'],
- $ariInfo['num_rooms']
- );
-
- $ariFormatted['hotel_ari']['room_types'][$roomTypeIndex] = array(
- 'id_room_type' => $roomTypeInfo['id_product'],
- 'base_price' => $roomTypePriceTE,
- 'base_price_with_tax' => $roomTypePriceTI,
- 'total_price' => $totalBookingPrice['total_price_tax_excl'],
- 'total_price_with_tax' => $totalBookingPrice['total_price_tax_incl']
- );
-
- $objRoomType = new Product($roomTypeInfo['id_product']);
- $ariFormatted['hotel_ari']['room_types'][$roomTypeIndex]['name'] = array();
- foreach ($this->objOutput->getObjectRender()->languages as $idLang) {
- $ariFormatted['hotel_ari']['room_types'][$roomTypeIndex]['name'][] = array(
- 'id' => $idLang,
- 'value' => $objRoomType->name[$idLang]
- );
- }
- // if only one lang than do not set name as array and set only value of the room
- if (count($ariFormatted['hotel_ari']['room_types'][$roomTypeIndex]['name']) == 1) {
- $ariFormatted['hotel_ari']['room_types'][$roomTypeIndex]['name'] = $ariFormatted['hotel_ari']['room_types'][$roomTypeIndex]['name'][0]['value'];
- }
-
- // rooms info of the room type
- if (isset($roomTypeInfo['data']) && $roomTypeInfo['data']) {
- $ariFormatted['hotel_ari']['room_types'][$roomTypeIndex]['rooms'] = array();
-
- foreach ($roomTypeInfo['data'] as $key => $roomsInfo) {
- $roomsAriInfo = array();
- if ($key == 'available') {
- $keyRoomAvailability = 'available';
- } elseif ($key == 'unavailable') {
- $keyRoomAvailability = 'unavailable';
- } elseif ($key == 'booked') {
- $keyRoomAvailability = 'booked';
- } elseif ($key == 'partially_available') {
- $keyRoomAvailability = 'partially_available';
- }
-
- if ($roomsInfo) {
- if ($key == 'partially_available') {
- foreach ($roomsInfo as $dateIndex => $partialRoomsInfo) {
- if (isset($partialRoomsInfo['rooms']) && $partialRoomsInfo['rooms']) {
- $roomsAriInfo[$dateIndex]['date_from'] = $partialRoomsInfo['date_from'];
- $roomsAriInfo[$dateIndex]['date_to'] = $partialRoomsInfo['date_to'];
-
- $roomsAriInfo[$dateIndex]['rooms'] = array();
- foreach ($partialRoomsInfo['rooms'] as $roomInfo) {
- $roomDetail = array();
- $roomDetail['id_room'] = $roomInfo['id_room'];
- $roomDetail['room_number'] = $roomInfo['room_num'];
-
- $roomsAriInfo[$dateIndex]['rooms'][] = $roomDetail;
- }
- }
- }
- } else {
- foreach ($roomsInfo as $roomIndex => $roomInfo) {
- $roomsAriInfo[$roomIndex]['id_room'] = $roomInfo['id_room'];
- $roomsAriInfo[$roomIndex]['room_number'] = $roomInfo['room_num'];
- }
- }
- }
-
- $ariFormatted['hotel_ari']['room_types'][$roomTypeIndex]['rooms'][$keyRoomAvailability] = array_values($roomsAriInfo);
+ // check if availability stats are available then only process further
+ if (isset($ariInfo['stats']) && $ariInfo['stats']) {
+ $dateAriInfo['total_rooms'] = $ariInfo['stats']['total_rooms'];
+ if (isset($ariInfo['stats']['num_avail'])) {
+ $dateAriInfo['total_available_rooms'] = $ariInfo['stats']['num_avail'];
+ }
+ if (isset($ariInfo['stats']['num_unavail'])) {
+ $dateAriInfo['total_unavailable_rooms'] = $ariInfo['stats']['num_unavail'];
+ }
+ if (isset($ariInfo['stats']['num_part_avai'])) {
+ $dateAriInfo['total_partial_available_rooms'] = $ariInfo['stats']['num_part_avai'];
+ }
+ if (isset($ariInfo['stats']['num_booked'])) {
+ $dateAriInfo['total_booked_rooms'] = $ariInfo['stats']['num_booked'];
}
}
- $ariFormatted['hotel_ari']['room_types'] = array_values($ariFormatted['hotel_ari']['room_types']);
+ // check if room type data is available then only process further
+ if (isset($ariInfo['rm_data']) && $ariInfo['rm_data']) {
+ $dateAriInfo['room_types'] = array();
+
+ foreach ($ariInfo['rm_data'] as $roomTypeIndex => $roomTypeInfo) {
+ // get feature price of room type
+ $roomTypePriceTE = HotelRoomTypeFeaturePricing::getRoomTypeFeaturePricesPerDay(
+ $roomTypeInfo['id_product'],
+ $ariInfo['date_from'],
+ $ariInfo['date_to'],
+ 0
+ );
+ $roomTypePriceTI = HotelRoomTypeFeaturePricing::getRoomTypeFeaturePricesPerDay(
+ $roomTypeInfo['id_product'],
+ $ariInfo['date_from'],
+ $ariInfo['date_to'],
+ 1
+ );
+ $totalBookingPrice = HotelRoomTypeFeaturePricing::getRoomTypeTotalPrice(
+ $roomTypeInfo['id_product'],
+ $ariInfo['date_from'],
+ $ariInfo['date_to'],
+ $ariInfo['num_rooms']
+ );
+
+ $dateAriInfo['room_types'][$roomTypeIndex] = array(
+ 'id_room_type' => $roomTypeInfo['id_product'],
+ 'base_price' => $roomTypePriceTE,
+ 'base_price_with_tax' => $roomTypePriceTI,
+ 'total_price' => $totalBookingPrice['total_price_tax_excl'],
+ 'total_price_with_tax' => $totalBookingPrice['total_price_tax_incl']
+ );
+
+ $objRoomType = new Product($roomTypeInfo['id_product']);
+ $dateAriInfo['room_types'][$roomTypeIndex]['name'] = array();
+ foreach ($this->objOutput->getObjectRender()->languages as $idLang) {
+ $dateAriInfo['room_types'][$roomTypeIndex]['name'][] = array(
+ 'id' => $idLang,
+ 'value' => $objRoomType->name[$idLang]
+ );
+ }
+ // if only one lang than do not set name as array and set only value of the room
+ if (count($dateAriInfo['room_types'][$roomTypeIndex]['name']) == 1) {
+ $dateAriInfo['room_types'][$roomTypeIndex]['name'] = $dateAriInfo['room_types'][$roomTypeIndex]['name'][0]['value'];
+ }
+
+ // rooms info of the room type
+ if (isset($roomTypeInfo['data']) && $roomTypeInfo['data']) {
+ $dateAriInfo['room_types'][$roomTypeIndex]['rooms'] = array();
+
+ foreach ($roomTypeInfo['data'] as $key => $roomsInfo) {
+ $roomsAriInfo = array();
+ if ($key == 'available') {
+ $keyRoomAvailability = 'available';
+ } elseif ($key == 'unavailable') {
+ $keyRoomAvailability = 'unavailable';
+ } elseif ($key == 'booked') {
+ $keyRoomAvailability = 'booked';
+ } elseif ($key == 'partially_available') {
+ $keyRoomAvailability = 'partially_available';
+ }
+
+ if ($roomsInfo) {
+ if ($key == 'partially_available') {
+ foreach ($roomsInfo as $dateIndex => $partialRoomsInfo) {
+ if (isset($partialRoomsInfo['rooms']) && $partialRoomsInfo['rooms']) {
+ $roomsAriInfo[$dateIndex]['date_from'] = $partialRoomsInfo['date_from'];
+ $roomsAriInfo[$dateIndex]['date_to'] = $partialRoomsInfo['date_to'];
+
+ $roomsAriInfo[$dateIndex]['rooms'] = array();
+ foreach ($partialRoomsInfo['rooms'] as $roomInfo) {
+ $roomDetail = array();
+ $roomDetail['id_room'] = $roomInfo['id_room'];
+ $roomDetail['room_number'] = $roomInfo['room_num'];
+
+ $roomsAriInfo[$dateIndex]['rooms'][] = $roomDetail;
+ }
+ }
+ }
+ } else {
+ foreach ($roomsInfo as $roomIndex => $roomInfo) {
+ $roomsAriInfo[$roomIndex]['id_room'] = $roomInfo['id_room'];
+ $roomsAriInfo[$roomIndex]['room_number'] = $roomInfo['room_num'];
+ }
+ }
+ }
+
+ $dateAriInfo['room_types'][$roomTypeIndex]['rooms'][$keyRoomAvailability] = array_values($roomsAriInfo);
+ }
+ }
+
+ $dateAriInfo['room_types'] = array_values($dateAriInfo['room_types']);
+ }
+ }
+
+ $ariFormatted[] = $dateAriInfo;
}
}
// change the content to the json form for api response
- $this->output .= json_encode($ariFormatted);
+ $ariReponse = [];
+ if ($dateWiseBreakdown) {
+ // if date wise breakup is requested the parent node will be 'hotel_aris' as per other APIs in QloApps (orders > order)
+ $ariReponse['hotel_aris'] = array_values($ariFormatted);
+ } else {
+ $ariReponse['hotel_ari'] = $ariFormatted[0];
+ }
+
+ $this->output .= json_encode($ariReponse);
$this->output = preg_replace_callback("/\\\\u([a-f0-9]{4})/", function ($matches) {
return iconv('UCS-4LE','UTF-8', pack('V', hexdec('U' . $matches[1])));
}, $this->output);
diff --git a/pdf/invoice.total-tab.tpl b/pdf/invoice.total-tab.tpl
index 2f70c1267..4de340a56 100644
--- a/pdf/invoice.total-tab.tpl
+++ b/pdf/invoice.total-tab.tpl
@@ -138,7 +138,7 @@
{l s='Due Amount' pdf='true'}
- {displayPrice currency=$order->id_currency price=($order->total_paid - $order->total_paid_real)}
+ {displayPrice currency=$order->id_currency price=($footer.total_paid_tax_incl - $footer.total_paid_real)}
|
{/if}