Files
hotel/modules/statsbestcategories/statsbestcategories.php
2026-10-28 10:53:54 +05:30

287 lines
12 KiB
PHP

<?php
/*
* 2007-2016 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2016 PrestaShop SA
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
if (!defined('_PS_VERSION_')) {
exit;
}
class StatsBestCategories extends ModuleGrid
{
private $html;
private $query;
private $columns;
private $default_sort_column;
private $default_sort_direction;
private $empty_message;
private $paging_message;
public function __construct()
{
$this->name = 'statsbestcategories';
$this->tab = 'analytics_stats';
$this->version = '1.5.6';
$this->author = 'PrestaShop';
$this->need_instance = 0;
parent::__construct();
$this->default_sort_column = 'totalRevenue';
$this->default_sort_direction = 'DESC';
$this->empty_message = $this->l('Empty recordset returned');
$this->paging_message = sprintf($this->l('Displaying %1$s of %2$s'), '{0} - {1}', '{2}');
$this->columns = array(
array(
'id' => 'name',
'header' => $this->l('Property Name'),
'dataIndex' => 'hotel_name',
'align' => 'center'
),
array(
'id' => 'totalRoomsBooked',
'header' => $this->l('Room nights booked'),
'dataIndex' => 'totalRoomsBooked',
'align' => 'center',
'tooltip' => $this->l('The room nights booked for the property.'),
),
array(
'id' => 'availableRooms',
'header' => $this->l('Available room nights'),
'dataIndex' => 'availableRooms',
'align' => 'center',
'tooltip' => $this->l('The total room nights available for booking for the property.'),
),
array(
'id' => 'totalOrders',
'header' => $this->l('Orders'),
'dataIndex' => 'totalOrders',
'align' => 'center',
),
array(
'id' => 'totalRevenue',
'header' => $this->l('Revenue'),
'dataIndex' => 'totalRevenue',
'align' => 'center',
),
array(
'id' => 'totalMargin',
'header' => $this->l('Margin'),
'dataIndex' => 'totalMargin',
'align' => 'center',
),
array(
'id' => 'averageRevenue',
'header' => $this->l('Avg. revenue/order'),
'dataIndex' => 'averageRevenue',
'align' => 'center',
),
);
$this->displayName = $this->l('Best hotels');
$this->description = $this->l('Adds a list of the best hotels to the Stats dashboard.');
$this->ps_versions_compliancy = array('min' => '1.6', 'max' => '1.7.0.99');
}
public function install()
{
return (parent::install() && $this->registerHook('AdminStatsModules'));
}
public function hookAdminStatsModules($params)
{
$engine_params = array(
'id' => 'id_category',
'title' => $this->displayName,
'columns' => $this->columns,
'defaultSortColumn' => $this->default_sort_column,
'defaultSortDirection' => $this->default_sort_direction,
'emptyMessage' => $this->empty_message,
'pagingMessage' => $this->paging_message,
);
if (Tools::getValue('export')) {
$this->csvExport($engine_params);
}
$this->html = '
<div class="panel-heading">
<i class="icon-sitemap"></i> '.$this->displayName.'
</div>';
$this->html .= $this->engine($engine_params).'
<div class="row form-horizontal">
<div class="col-md-3">
<a class="btn btn-default export-csv" href="'.Tools::safeOutput($_SERVER['REQUEST_URI'].'&export=1').'">
<i class="icon-cloud-download"></i> '.$this->l('CSV Export').'
</a>
</div>
</div>';
return $this->html;
}
public function getData()
{
$currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
$date_between = $this->getDate();
$date_from = date('Y-m-d', strtotime($this->_employee->stats_date_from));
$date_to = date('Y-m-d', strtotime($this->_employee->stats_date_to));
if ($date_from == $date_to) {
$date_to = date('Y-m-d', strtotime('+1 day', strtotime($date_to)));
}
$id_lang = $this->getLang();
//If column 'order_detail.original_wholesale_price' does not exist, create it
Db::getInstance(_PS_USE_SQL_SLAVE_)->query('SHOW COLUMNS FROM `'._DB_PREFIX_.'order_detail` LIKE "original_wholesale_price"');
if (Db::getInstance()->NumRows() == 0) {
Db::getInstance()->execute('ALTER TABLE `'._DB_PREFIX_.'order_detail` ADD `original_wholesale_price` DECIMAL( 20, 6 ) NOT NULL DEFAULT "0.000000"');
}
// Get best hotels
$this->query = 'SELECT hbi.`id`, hbil.`hotel_name` AS hotel_name,
(
SELECT IFNULL(SUM(DATEDIFF(LEAST(hbd.`date_to`, "'.pSQL($date_to).'"), GREATEST(hbd.`date_from`, "'.pSQL($date_from).'"))), 0)
FROM `'._DB_PREFIX_.'htl_booking_detail` hbd
LEFT JOIN `'._DB_PREFIX_.'orders` o ON (o.`id_order` = hbd.`id_order`)
WHERE hbd.`id_hotel` = hbi.`id` AND o.`valid` = 1 AND hbd.`id` NOT IN ('.OrderReturn::getRefundedBookingIdsSubquery().')
AND hbd.`date_to` > "'.pSQL($date_from).'" AND hbd.`date_from` < "'.pSQL($date_to).'"
) AS totalRoomsBooked,
(
SELECT SUM(max_room_nights) - SUM(disabled_room_nights)
FROM (
SELECT hri.`id_hotel`, DATEDIFF("'.pSQL($date_to).'", "'.pSQL($date_from).'") AS max_room_nights,
CASE
WHEN hri.`id_status` = '.(int) HotelRoomInformation::STATUS_INACTIVE.' THEN DATEDIFF("'.pSQL($date_to).'", "'.pSQL($date_from).'")
WHEN hri.`id_status` = '.(int) HotelRoomInformation::STATUS_ACTIVE.' THEN IF(hrdd.`date_to` > "'.pSQL($date_from).'" AND hrdd.`date_from` < "'.pSQL($date_to).'", SUM(ABS(DATEDIFF(LEAST(hrdd.`date_to`, "'.pSQL($date_to).'"), GREATEST(hrdd.`date_from`, "'.pSQL($date_from).'")))), 0)
ELSE 0
END AS disabled_room_nights
FROM `'._DB_PREFIX_.'htl_room_information` hri
LEFT JOIN `'._DB_PREFIX_.'htl_room_disable_dates` hrdd
ON (hrdd.`id_room` = hri.`id`)
GROUP BY hri.`id`
) AS t
WHERE t.`id_hotel` = hbi.`id`
) AS totalRooms,
(
SELECT COUNT(DISTINCT o.`id_order`)
FROM `'._DB_PREFIX_.'orders` o
WHERE `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59" AND o.valid = 1
AND (
EXISTS (
SELECT 1
FROM `'._DB_PREFIX_.'htl_booking_detail` hbd
WHERE hbd.`id_order` = o.`id_order` AND hbd.`id_hotel` = hbi.`id`
) OR EXISTS (
SELECT 1
FROM `'._DB_PREFIX_.'service_product_order_detail` spod
WHERE spod.`id_order` = o.`id_order` AND spod.`id_hotel` = hbi.`id`
)
)
) AS totalOrders,
(
SELECT ROUND(SUM(total_paid_tax_excl / o.`conversion_rate`), 2)
FROM `'._DB_PREFIX_.'orders` o
WHERE o.valid = 1 AND `invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59"
AND (
EXISTS (
SELECT 1
FROM `'._DB_PREFIX_.'htl_booking_detail` hbd
WHERE hbd.`id_order` = o.`id_order` AND hbd.`id_hotel` = hbi.`id`
) OR EXISTS (
SELECT 1
FROM `'._DB_PREFIX_.'service_product_order_detail` spod
WHERE spod.`id_order` = o.`id_order` AND spod.`id_hotel` = hbi.`id`
)
)
) AS totalRevenue,
(
SELECT IFNULL(
ROUND(SUM(
CASE
WHEN od.`original_wholesale_price` <> 0 THEN od.`original_wholesale_price`
WHEN p.`wholesale_price` <> 0 THEN p.`wholesale_price`
ELSE 0
END
), 2)
, 0)
FROM `'._DB_PREFIX_.'order_detail` od
LEFT JOIN `'._DB_PREFIX_.'orders` o ON (od.`id_order` = o.`id_order`)
LEFT JOIN `'._DB_PREFIX_.'product` p ON (p.`id_product` = od.`product_id`)
WHERE o.valid = 1 AND o.`invoice_date` BETWEEN "'.pSQL($date_from).' 00:00:00" AND "'.pSQL($date_to).' 23:59:59"
AND (
EXISTS (
SELECT 1
FROM `'._DB_PREFIX_.'htl_booking_detail` hbd
WHERE hbd.`id_order` = o.`id_order` AND hbd.`id_hotel` = hbi.`id`
) OR EXISTS (
SELECT 1
FROM `'._DB_PREFIX_.'service_product_order_detail` spod
WHERE spod.`id_order` = o.`id_order` AND spod.`id_hotel` = hbi.`id`
)
)
) AS totalOperatingCost
FROM `'._DB_PREFIX_.'htl_branch_info` hbi
LEFT JOIN `'._DB_PREFIX_.'htl_branch_info_lang` hbil
ON (hbil.`id` = hbi.`id` AND hbil.`id_lang` = '.(int)$id_lang .')
WHERE 1 '.HotelBranchInformation::addHotelRestriction(false, 'hbi', 'id').'
GROUP BY (hbi.`id`)';
if (Validate::IsName($this->_sort)) {
$this->query .= ' ORDER BY `'.bqSQL($this->_sort).'`';
if (isset($this->_direction) && Validate::isSortDirection($this->_direction)) {
$this->query .= ' '.$this->_direction;
}
}
if (($this->_start === 0 || Validate::IsUnsignedInt($this->_start)) && Validate::IsUnsignedInt($this->_limit)) {
$this->query .= ' LIMIT '.(int)$this->_start.', '.(int)$this->_limit;
}
$values = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($this->query);
$this->_totalCount = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT FOUND_ROWS()');
foreach ($values as &$value) {
if (Tools::getValue('export') == false) {
$value['hotel_name'] = '<a href="'.$this->context->link->getAdminLink('AdminAddHotel').'&id='.$value['id'].'&updatehtl_branch_info" target="_blank">'.$value['hotel_name'].'</a>';
}
$value['totalMargin'] = 0;
if (((float) $value['totalRevenue']) > 0 && ((float) $value['totalOperatingCost']) > 0) {
$value['totalMargin'] = max($value['totalRevenue'] - $value['totalOperatingCost'], 0);
}
$value['totalMargin'] = Tools::displayPrice($value['totalMargin'], $currency);
$value['availableRooms'] = max($value['totalRooms'] - $value['totalRoomsBooked'], 0); // availableRooms can be negative if more rooms are disabled than available for booking
$value['averageRevenue'] = $value['totalRoomsBooked'] ? ((float) $value['totalRevenue'] / (int) $value['totalOrders']) : 0;
$value['averageRevenue'] = Tools::displayPrice((float) $value['averageRevenue'], $currency);
$value['totalRevenue'] = Tools::displayPrice((float) $value['totalRevenue'], $currency);
}
$this->_values = $values;
}
}