Merge branch 'develop' into gli-1949

This commit is contained in:
Shreesh Arora
2024-08-07 13:25:49 +05:30
18 changed files with 733 additions and 460 deletions

View File

@@ -82,4 +82,17 @@
max-height: 200px
.panel-refund-request .refunded_amount
margin-top: 2px
margin-top: 2px
.panel-guest_address
.panel-heading
align-items: center
display: flex
gap: 10px
justify-content: space-between
.panel-title
width: 100%
.dropdown-menu
right: 0
left: unset
font-size: 14px

View File

@@ -634,128 +634,60 @@
</div>
{/if}
<!-- Tab nav -->
<div class="row" style="display:none">
<ul class="nav nav-tabs" id="tabAddresses">
<li class="active">
<a href="#addressShipping">
<i class="icon-truck"></i>
{l s='Shipping address'}
</a>
</li>
<li>
<a href="#addressInvoice">
<i class="icon-file-text"></i>
{l s='Invoice address'}
</a>
</li>
</ul>
<!-- Tab content -->
<div class="tab-content panel">
<!-- Tab status -->
<div class="tab-pane in active" id="addressShipping">
<!-- Addresses -->
<h4 class="visible-print">{l s='Shipping address'}</h4>
{if !$order->isVirtual()}
<!-- Shipping address -->
{if $can_edit}
<form class="form-horizontal hidden-print" method="post" action="{$link->getAdminLink('AdminOrders')|escape:'html':'UTF-8'}&amp;vieworder&amp;id_order={$order->id|intval}">
<div class="form-group">
<div class="col-lg-9">
<select name="id_address">
{foreach from=$customer_addresses item=address}
<option value="{$address['id_address']}"
{if $address['id_address'] == $order->id_address_delivery}
selected="selected"
{/if}>
{$address['alias']} -
{$address['address1']}
{$address['postcode']}
{$address['city']}
{if !empty($address['state'])}
{$address['state']}
{/if},
{$address['country']}
</option>
{/foreach}
</select>
</div>
<div class="col-lg-3">
<button class="btn btn-default" type="submit" name="submitAddressShipping"><i class="icon-refresh"></i> {l s='Change'}</button>
</div>
</div>
</form>
{/if}
<div class="well">
<div class="row">
<div class="col-sm-6">
<a class="btn btn-default pull-right" href="?tab=AdminAddresses&amp;id_address={$addresses.delivery->id}&amp;addaddress&amp;realedit=1&amp;id_order={$order->id}&amp;address_type=1&amp;token={getAdminToken tab='AdminAddresses'}&amp;back={$smarty.server.REQUEST_URI|urlencode}">
<i class="icon-pencil"></i>
{l s='Edit'}
</a>
{displayAddressDetail address=$addresses.delivery newLine='<br />'}
{if $addresses.delivery->other}
<hr />{$addresses.delivery->other}<br />
{/if}
</div>
</div>
</div>
{/if}
</div>
<div class="tab-pane " id="addressInvoice">
<!-- Invoice address -->
<h4 class="visible-print">{l s='Invoice address'}</h4>
{if $can_edit}
<form class="form-horizontal hidden-print" method="post" action="{$link->getAdminLink('AdminOrders')|escape:'html':'UTF-8'}&amp;vieworder&amp;id_order={$order->id|intval}">
<div class="form-group">
<div class="col-lg-9">
<select name="id_address">
{foreach from=$customer_addresses item=address}
<option value="{$address['id_address']}"
{if $address['id_address'] == $order->id_address_invoice}
selected="selected"
{/if}>
{$address['alias']} -
{$address['address1']}
{$address['postcode']}
{$address['city']}
{if !empty($address['state'])}
{$address['state']}
{/if},
{$address['country']}
</option>
{/foreach}
</select>
</div>
<div class="col-lg-3">
<button class="btn btn-default" type="submit" name="submitAddressInvoice"><i class="icon-refresh"></i> {l s='Change'}</button>
</div>
</div>
</form>
{/if}
<div class="well">
<div class="row">
<div class="col-sm-6">
<a class="btn btn-default pull-right" href="?tab=AdminAddresses&amp;id_address={$addresses.invoice->id}&amp;addaddress&amp;realedit=1&amp;id_order={$order->id}&amp;address_type=2&amp;back={$smarty.server.REQUEST_URI|urlencode}&amp;token={getAdminToken tab='AdminAddresses'}">
<i class="icon-pencil"></i>
{l s='Edit'}
</a>
{displayAddressDetail address=$addresses.invoice newLine='<br />'}
{if $addresses.invoice->other}
<hr />{$addresses.invoice->other}<br />
</div>
<div class="panel panel-guest_address">
<div class="panel-heading">
<span class="panel-title"><i class="icon icon-envelope"></i> &nbsp;{l s='Customer Address'}</span>
{if $can_edit}
{if $idOrderAddressInvoice}
<button id="edit_guest_address" class="btn btn-primary pull-right fancybox" href="{$link->getAdminLink('AdminAddresses')}&amp;id_address={$idOrderAddressInvoice}&amp;updateaddress&amp;id_order={$order->id|intval}&amp;address_type=2&amp;realedit=1&amp;liteDisplaying=1&amp;submitFormAjax=1#">
<i class="icon-pencil"></i> {l s='Edit'}
</button>
{if (!$idCurrentAddress || ($idCurrentAddress != $idOrderAddressInvoice)) || $ordersWithDiffInvAddr}
<div class="guest_address_actions dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="icon-ellipsis-vertical"></i>
</a>
<ul class="dropdown-menu">
{if $ordersWithDiffInvAddr}
<li><a href="{$current_index}&amp;vieworder&amp;token={$smarty.get.token|escape:'html':'UTF-8'}&amp;id_order={$order->id|intval}&amp;action=set_old_orders_address">{l s='Set for all orders'}</a></li>
{/if}
</div>
{if !$idCurrentAddress || ($idCurrentAddress != $idOrderAddressInvoice)}
<li><a href="{$current_index}&amp;vieworder&amp;token={$smarty.get.token|escape:'html':'UTF-8'}&amp;id_order={$order->id|intval}&amp;action=set_address_current_address">{l s='Set as current address'}</a></li>
{/if}
</ul>
</div>
{/if}
{else}
<button id="add_guest_address" class="btn btn-primary pull-right fancybox" href="{$link->getAdminLink('AdminAddresses')}&amp;addaddress&amp;id_order={$order->id|intval}&amp;address_type=2&amp;id_customer={$order->id_customer}&amp;liteDisplaying=1&amp;submitFormAjax=1#">
<i class="icon-plus-circle"></i> {l s='Add Address'}
</button>
{if $idCurrentAddress}
<div class="guest_address_actions dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="icon-ellipsis-vertical"></i>
</a>
<ul class="dropdown-menu">
<li><a href="{$current_index}&amp;vieworder&amp;token={$smarty.get.token|escape:'html':'UTF-8'}&amp;id_order={$order->id|intval}&amp;action=set_order_active_address">{l s='Set current address for this order'}</a></li>
</ul>
</div>
{/if}
{/if}
{/if}
</div>
<div class="row">
{if $guestFormattedAddress}
{$guestFormattedAddress}
{else}
<div class="list-empty">
<div class="list-empty-msg">
<i class="icon-warning-sign list-empty-icon"></i>
{l s='Guest address not found.'}
</div>
</div>
</div>
{/if}
</div>
<script>
$('#tabAddresses a').click(function (e) {
e.preventDefault()
$(this).tab('show')
})
</script>
</div>
{* Order Internal notes *}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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]);

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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(), "<br />");
// 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;

View File

@@ -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

View File

@@ -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(

View File

@@ -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) {

View File

@@ -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'];

View File

@@ -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;
}

View File

@@ -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)) {

View File

@@ -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);

View File

@@ -138,7 +138,7 @@
{l s='Due Amount' pdf='true'}
</td>
<td class="white">
{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)}
</td>
</tr>
{/if}