@@ -0,0 +1,18 @@
|
||||
{*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License version 3.0
|
||||
* that is bundled with this package in the file LICENSE.md
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/license/osl-3-0-php
|
||||
*
|
||||
* @author Webkul IN
|
||||
* @copyright Since 2010 Webkul
|
||||
* @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0
|
||||
*}
|
||||
{extends file="helpers/list/list_header.tpl"}
|
||||
{block name="override_form_extra"}
|
||||
{if isset($smarty.get.id_source_type)}
|
||||
<input type="hidden" name="id_source_type" value="{$smarty.get.id_source_type|intval}" />
|
||||
{/if}
|
||||
{/block}
|
||||
@@ -0,0 +1,36 @@
|
||||
{*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License version 3.0
|
||||
* that is bundled with this package in the file LICENSE.md
|
||||
*
|
||||
* @author Webkul IN
|
||||
* @copyright Since 2010 Webkul
|
||||
* @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0
|
||||
*}
|
||||
<form action="{$current_index}&token={$token}" method="post">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>{l s='Current Source'}</label>
|
||||
<select name="merge_current_source" id="merge_current_source" class="form-control">
|
||||
{foreach from=$sources item=source}
|
||||
<option value="{$source.id_source}"{if $source.id_source == $id_current_source} selected="selected"{/if}>{$source.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{l s='Target Source'}</label>
|
||||
<select name="merge_target_source" id="merge_target_source" class="form-control">
|
||||
{foreach from=$sources item=source}
|
||||
<option value="{$source.id_source}">{$source.name}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
<p class="help-block">{l s='Every order currently attributed to Current Source will be reattributed to Target Source. Current Source itself is left as-is.'}</p>
|
||||
<input type="hidden" name="id_source_type" value="{$id_source_type|intval}" />
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{l s='Cancel'}</button>
|
||||
<button type="submit" name="submitMergeSource" class="btn btn-primary">{l s='Update'}</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -32,5 +32,6 @@ class BoOrder extends PaymentModule
|
||||
$this->validateOrderAmount = false;
|
||||
// Default payment type for backoffice order should be PAY_AT_HOTEL
|
||||
$this->payment_type = OrderPayment::PAYMENT_TYPE_PAY_AT_HOTEL;
|
||||
$this->idBookingSource = Source::getIdByCode('WALKIN');
|
||||
}
|
||||
}
|
||||
237
classes/BusinessSource.php
Normal file
237
classes/BusinessSource.php
Normal file
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License version 3.0
|
||||
* that is bundled with this package in the file LICENSE.md
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/license/osl-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 support@qloapps.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade QloApps to newer
|
||||
* versions in the future. If you wish to customize QloApps for your needs
|
||||
* please refer to https://store.webkul.com/customisation-guidelines for more information.
|
||||
*
|
||||
* @author Webkul IN
|
||||
* @copyright Since 2010 Webkul
|
||||
* @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0
|
||||
*/
|
||||
|
||||
class BusinessSourceCore extends ObjectModel
|
||||
{
|
||||
public $name;
|
||||
public $source_type_code;
|
||||
public $position;
|
||||
public $unremovable;
|
||||
public $active;
|
||||
public $deleted = 0;
|
||||
public $date_add;
|
||||
public $date_upd;
|
||||
|
||||
public static $definition = array(
|
||||
'table' => 'business_source',
|
||||
'primary' => 'id_source_type',
|
||||
'multilang' => true,
|
||||
'fields' => array(
|
||||
'source_type_code' => array('type' => self::TYPE_STRING, 'validate' => 'isModuleName', 'required' => true, 'size' => 64),
|
||||
'position' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
|
||||
'unremovable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
|
||||
'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
|
||||
'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
|
||||
'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'),
|
||||
'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'),
|
||||
'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64),
|
||||
),
|
||||
);
|
||||
|
||||
public function add($autodate = true, $nullValues = false)
|
||||
{
|
||||
if ($this->position <= 0) {
|
||||
$this->position = BusinessSource::getHigherPosition() + 1;
|
||||
}
|
||||
|
||||
return parent::add($autodate, $nullValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int Highest current position among non-deleted Business Sources, or -1 if none exist
|
||||
*/
|
||||
public static function getHigherPosition()
|
||||
{
|
||||
$position = Db::getInstance()->getValue(
|
||||
'SELECT MAX(`position`) FROM `'._DB_PREFIX_.'business_source` WHERE `deleted` = 0'
|
||||
);
|
||||
|
||||
return is_numeric($position) ? (int)$position : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move this Business Source up/down the list.
|
||||
* @param bool $way Up (1) or Down (0)
|
||||
* @param int $position
|
||||
* @return bool
|
||||
*/
|
||||
public function updatePosition($way, $position)
|
||||
{
|
||||
if (!$res = Db::getInstance()->executeS('
|
||||
SELECT `position`, `id_source_type`
|
||||
FROM `'._DB_PREFIX_.'business_source`
|
||||
WHERE `deleted` = 0
|
||||
ORDER BY `position` ASC'
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$moved_item = null;
|
||||
foreach ($res as $row) {
|
||||
if ((int)$row['id_source_type'] == (int)$this->id) {
|
||||
$moved_item = $row;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$moved_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (Db::getInstance()->execute('
|
||||
UPDATE `'._DB_PREFIX_.'business_source`
|
||||
SET `position` = `position` '.($way ? '- 1' : '+ 1').'
|
||||
WHERE `deleted` = 0 AND `position`
|
||||
'.($way
|
||||
? '> '.(int)$moved_item['position'].' AND `position` <= '.(int)$position
|
||||
: '< '.(int)$moved_item['position'].' AND `position` >= '.(int)$position)
|
||||
) && Db::getInstance()->execute('
|
||||
UPDATE `'._DB_PREFIX_.'business_source`
|
||||
SET `position` = '.(int)$position.'
|
||||
WHERE `id_source_type` = '.(int)$moved_item['id_source_type']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder Business Source positions into a contiguous 0..N-1 sequence. Call after a delete.
|
||||
* @return bool
|
||||
*/
|
||||
public static function cleanPositions()
|
||||
{
|
||||
$return = true;
|
||||
|
||||
$result = Db::getInstance()->executeS('
|
||||
SELECT `id_source_type`
|
||||
FROM `'._DB_PREFIX_.'business_source`
|
||||
WHERE `deleted` = 0
|
||||
ORDER BY `position` ASC'
|
||||
);
|
||||
|
||||
$i = 0;
|
||||
foreach ($result as $row) {
|
||||
$return = Db::getInstance()->execute('
|
||||
UPDATE `'._DB_PREFIX_.'business_source`
|
||||
SET `position` = '.(int)$i++.'
|
||||
WHERE `id_source_type` = '.(int)$row['id_source_type']
|
||||
) && $return;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public static function codeExists($code, $idExclude = 0)
|
||||
{
|
||||
return (bool)Db::getInstance()->getValue(
|
||||
'SELECT `id_source_type` FROM `'._DB_PREFIX_.'business_source`
|
||||
WHERE `source_type_code` = \''.pSQL($code).'\' AND `id_source_type` != '.(int)$idExclude
|
||||
);
|
||||
}
|
||||
|
||||
public static function getUnremovableIds()
|
||||
{
|
||||
$rows = Db::getInstance()->executeS(
|
||||
'SELECT `id_source_type` FROM `'._DB_PREFIX_.'business_source` WHERE `unremovable` = 1 AND `deleted` = 0'
|
||||
);
|
||||
|
||||
return array_map('intval', array_column($rows, 'id_source_type'));
|
||||
}
|
||||
|
||||
public static function getActiveList($idLang)
|
||||
{
|
||||
return Db::getInstance()->executeS('
|
||||
SELECT bs.`id_source_type`, bsl.`name`
|
||||
FROM `'._DB_PREFIX_.'business_source` bs
|
||||
LEFT JOIN `'._DB_PREFIX_.'business_source_lang` bsl
|
||||
ON (bsl.`id_source_type` = bs.`id_source_type` AND bsl.`id_lang` = '.(int)$idLang.')
|
||||
WHERE bs.`active` = 1 AND bs.`deleted` = 0
|
||||
ORDER BY bs.`position` ASC
|
||||
');
|
||||
}
|
||||
|
||||
public function isRemovable()
|
||||
{
|
||||
return !$this->unremovable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool True if any Booking Source under this Business Source — deleted or not —
|
||||
* is referenced by an order. A soft-deleted Booking Source still referenced by a historical
|
||||
* order must keep resolving to a Business Source name too, so this still blocks deletion.
|
||||
*/
|
||||
public function hasSourceUsedByOrder()
|
||||
{
|
||||
return (bool)Db::getInstance()->getValue(
|
||||
'SELECT COUNT(*) FROM `'._DB_PREFIX_.'source` s
|
||||
INNER JOIN `'._DB_PREFIX_.'orders` o ON o.`id_source` = s.`id_source`
|
||||
WHERE s.`id_source_type` = '.(int)$this->id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int Total orders placed across every Booking Source under this Business Source —
|
||||
* the denominator for each Booking Source's own percentage within this category's
|
||||
* drill-down list (as opposed to a share of every order in the system).
|
||||
*/
|
||||
public function getOrderCount()
|
||||
{
|
||||
return (int)Db::getInstance()->getValue(
|
||||
'SELECT COUNT(*) FROM `'._DB_PREFIX_.'source` s
|
||||
INNER JOIN `'._DB_PREFIX_.'orders` o ON o.`id_source` = s.`id_source`
|
||||
WHERE s.`id_source_type` = '.(int)$this->id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deleting a Business Source deletes every Booking Source under it (each through its own
|
||||
* delete() rule — soft-deleted if order-linked, hard-deleted otherwise). If any of them
|
||||
* turns out to be order-linked, this Business Source is soft-deleted too, the same way, so
|
||||
* historical orders keep resolving a category name; otherwise it hard-deletes for real.
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
if (!$this->isRemovable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$keepSoft = $this->hasSourceUsedByOrder();
|
||||
|
||||
$sources = Db::getInstance()->executeS(
|
||||
'SELECT `id_source` FROM `'._DB_PREFIX_.'source` WHERE `id_source_type` = '.(int)$this->id.' AND `deleted` = 0'
|
||||
);
|
||||
foreach ($sources as $row) {
|
||||
$objSource = new Source((int)$row['id_source']);
|
||||
if (!$objSource->delete()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($keepSoft) {
|
||||
$this->deleted = 1;
|
||||
if (!$this->update()) {
|
||||
return false;
|
||||
}
|
||||
} elseif (!parent::delete()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return BusinessSource::cleanPositions();
|
||||
}
|
||||
}
|
||||
@@ -352,6 +352,13 @@ abstract class PaymentModuleCore extends Module
|
||||
$order->source = Configuration::get('PS_SHOP_DOMAIN');
|
||||
}
|
||||
|
||||
// Booking Source (business categorization, e.g. Direct Website/Walk-in/OTA) —
|
||||
if (isset($this->idBookingSource) && $this->idBookingSource) {
|
||||
$order->id_source = (int)$this->idBookingSource;
|
||||
} else {
|
||||
$order->id_source = Source::getDefaultSourceId();
|
||||
}
|
||||
|
||||
if (self::DEBUG_MODE) {
|
||||
PrestaShopLogger::addLog('PaymentModule::validateOrder - Order is about to be added', 1, null, 'Cart', (int)$id_cart, true);
|
||||
}
|
||||
|
||||
222
classes/Source.php
Normal file
222
classes/Source.php
Normal file
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License version 3.0
|
||||
* that is bundled with this package in the file LICENSE.md
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/license/osl-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 support@qloapps.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade QloApps to newer
|
||||
* versions in the future. If you wish to customize QloApps for your needs
|
||||
* please refer to https://store.webkul.com/customisation-guidelines for more information.
|
||||
*
|
||||
* @author Webkul IN
|
||||
* @copyright Since 2010 Webkul
|
||||
* @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0
|
||||
*/
|
||||
|
||||
class SourceCore extends ObjectModel
|
||||
{
|
||||
public $name;
|
||||
public $id_source_type;
|
||||
public $source_code;
|
||||
public $position;
|
||||
public $unremovable;
|
||||
public $active;
|
||||
public $deleted = 0;
|
||||
public $date_add;
|
||||
public $date_upd;
|
||||
|
||||
public static $definition = array(
|
||||
'table' => 'source',
|
||||
'primary' => 'id_source',
|
||||
'multilang' => true,
|
||||
'fields' => array(
|
||||
'id_source_type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
|
||||
'source_code' => array('type' => self::TYPE_STRING, 'validate' => 'isModuleName', 'required' => true, 'size' => 64),
|
||||
'position' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
|
||||
'unremovable' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
|
||||
'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
|
||||
'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
|
||||
'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'),
|
||||
'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'),
|
||||
'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64),
|
||||
),
|
||||
);
|
||||
|
||||
public function add($autodate = true, $nullValues = false)
|
||||
{
|
||||
if ($this->position <= 0) {
|
||||
$this->position = Source::getHigherPosition($this->id_source_type) + 1;
|
||||
}
|
||||
|
||||
return parent::add($autodate, $nullValues);
|
||||
}
|
||||
|
||||
public static function getHigherPosition($idSourceType)
|
||||
{
|
||||
$position = Db::getInstance()->getValue(
|
||||
'SELECT MAX(`position`) FROM `'._DB_PREFIX_.'source`
|
||||
WHERE `id_source_type` = '.(int)$idSourceType.' AND `deleted` = 0'
|
||||
);
|
||||
|
||||
return is_numeric($position) ? (int)$position : -1;
|
||||
}
|
||||
|
||||
public function updatePosition($way, $position)
|
||||
{
|
||||
if (!$res = Db::getInstance()->executeS('
|
||||
SELECT `position`, `id_source`
|
||||
FROM `'._DB_PREFIX_.'source`
|
||||
WHERE `id_source_type` = '.(int)$this->id_source_type.' AND `deleted` = 0
|
||||
ORDER BY `position` ASC'
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$moved_item = null;
|
||||
foreach ($res as $row) {
|
||||
if ((int)$row['id_source'] == (int)$this->id) {
|
||||
$moved_item = $row;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$moved_item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (Db::getInstance()->execute('
|
||||
UPDATE `'._DB_PREFIX_.'source`
|
||||
SET `position` = `position` '.($way ? '- 1' : '+ 1').'
|
||||
WHERE `id_source_type` = '.(int)$this->id_source_type.' AND `deleted` = 0 AND `position`
|
||||
'.($way
|
||||
? '> '.(int)$moved_item['position'].' AND `position` <= '.(int)$position
|
||||
: '< '.(int)$moved_item['position'].' AND `position` >= '.(int)$position)
|
||||
) && Db::getInstance()->execute('
|
||||
UPDATE `'._DB_PREFIX_.'source`
|
||||
SET `position` = '.(int)$position.'
|
||||
WHERE `id_source` = '.(int)$moved_item['id_source']));
|
||||
}
|
||||
|
||||
public static function codeExists($code, $idExclude = 0)
|
||||
{
|
||||
return (bool)Db::getInstance()->getValue(
|
||||
'SELECT `id_source` FROM `'._DB_PREFIX_.'source`
|
||||
WHERE `source_code` = \''.pSQL($code).'\' AND `id_source` != '.(int)$idExclude
|
||||
);
|
||||
}
|
||||
|
||||
public static function getIdByCode($code)
|
||||
{
|
||||
return (int)Db::getInstance()->getValue(
|
||||
'SELECT `id_source` FROM `'._DB_PREFIX_.'source`
|
||||
WHERE `source_code` = \''.pSQL($code).'\' AND `deleted` = 0'
|
||||
);
|
||||
}
|
||||
|
||||
public static function getUnremovableIds()
|
||||
{
|
||||
$rows = Db::getInstance()->executeS(
|
||||
'SELECT `id_source` FROM `'._DB_PREFIX_.'source` WHERE `unremovable` = 1 AND `deleted` = 0'
|
||||
);
|
||||
|
||||
return array_map('intval', array_column($rows, 'id_source'));
|
||||
}
|
||||
|
||||
public static function getActiveListForType($idSourceType, $idLang)
|
||||
{
|
||||
return Db::getInstance()->executeS('
|
||||
SELECT a.`id_source`, al.`name`
|
||||
FROM `'._DB_PREFIX_.'source` a
|
||||
LEFT JOIN `'._DB_PREFIX_.'source_lang` al ON (al.`id_source` = a.`id_source` AND al.`id_lang` = '.(int)$idLang.')
|
||||
WHERE a.`id_source_type` = '.(int)$idSourceType.' AND a.`deleted` = 0 AND a.`active` = 1
|
||||
ORDER BY a.`position` ASC
|
||||
');
|
||||
}
|
||||
|
||||
public static function getSourcesUsedInOrders($idLang)
|
||||
{
|
||||
return Db::getInstance()->executeS('
|
||||
SELECT DISTINCT o.`id_source`, sl.`name`
|
||||
FROM `'._DB_PREFIX_.'orders` o
|
||||
INNER JOIN `'._DB_PREFIX_.'source` s ON (s.`id_source` = o.`id_source`)
|
||||
LEFT JOIN `'._DB_PREFIX_.'source_lang` sl ON (sl.`id_source` = s.`id_source` AND sl.`id_lang` = '.(int)$idLang.')
|
||||
');
|
||||
}
|
||||
|
||||
public static function cleanPositions($idSourceType)
|
||||
{
|
||||
$return = true;
|
||||
|
||||
$result = Db::getInstance()->executeS('
|
||||
SELECT `id_source`
|
||||
FROM `'._DB_PREFIX_.'source`
|
||||
WHERE `id_source_type` = '.(int)$idSourceType.' AND `deleted` = 0
|
||||
ORDER BY `position` ASC'
|
||||
);
|
||||
|
||||
$i = 0;
|
||||
foreach ($result as $row) {
|
||||
$return = Db::getInstance()->execute('
|
||||
UPDATE `'._DB_PREFIX_.'source`
|
||||
SET `position` = '.(int)$i++.'
|
||||
WHERE `id_source` = '.(int)$row['id_source']
|
||||
) && $return;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function isRemovable()
|
||||
{
|
||||
return !$this->unremovable;
|
||||
}
|
||||
|
||||
public function isUsedByOrder()
|
||||
{
|
||||
return (bool)Db::getInstance()->getValue(
|
||||
'SELECT COUNT(*) FROM `'._DB_PREFIX_.'orders` WHERE `id_source` = '.(int)$this->id
|
||||
);
|
||||
}
|
||||
|
||||
public function mergeOrdersInto($idTargetSource)
|
||||
{
|
||||
return (bool)Db::getInstance()->execute(
|
||||
'UPDATE `'._DB_PREFIX_.'orders` SET `id_source` = '.(int)$idTargetSource.' WHERE `id_source` = '.(int)$this->id
|
||||
);
|
||||
}
|
||||
|
||||
public static function getTotalOrderCount()
|
||||
{
|
||||
return (int)Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'orders`');
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
if (!$this->isRemovable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->isUsedByOrder()) {
|
||||
$this->deleted = 1;
|
||||
if (!$this->update()) {
|
||||
return false;
|
||||
}
|
||||
} elseif (!parent::delete()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Source::cleanPositions($this->id_source_type);
|
||||
}
|
||||
|
||||
public static function getDefaultSourceId()
|
||||
{
|
||||
return (int)Configuration::get('PS_DEFAULT_BOOKING_SOURCE');
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ class AdminOrdersControllerCore extends AdminController
|
||||
|
||||
protected $statuses_array = array();
|
||||
protected $all_order_sources = array();
|
||||
protected $bookingSourcesArray = array();
|
||||
protected $hotelsArray = array();
|
||||
protected $roomTypesArray = array();
|
||||
protected $roomsArray = array();
|
||||
@@ -74,6 +75,10 @@ class AdminOrdersControllerCore extends AdminController
|
||||
hbd.`id_room` AS id_room_information,
|
||||
(SELECT COUNT(spod.`id_service_product_order_detail`) FROM `'._DB_PREFIX_.'service_product_order_detail` spod WHERE spod.`id_order` = a.`id_order` AND spod.`id_htl_booking_detail`=0) as num_products';
|
||||
|
||||
$this->_select .= ',
|
||||
(SELECT sl.`name` FROM `'._DB_PREFIX_.'source` s LEFT JOIN `'._DB_PREFIX_.'source_lang` sl ON (sl.`id_source` = s.`id_source` AND sl.`id_lang` = '.(int)$this->context->language->id.') WHERE s.`id_source` = a.`id_source`) AS `booking_source_name`,
|
||||
(SELECT s.`source_code` FROM `'._DB_PREFIX_.'source` s WHERE s.`id_source` = a.`id_source`) AS `booking_source_code`';
|
||||
|
||||
$this->_join = '
|
||||
LEFT JOIN `'._DB_PREFIX_.'customer` c ON (c.`id_customer` = a.`id_customer`)
|
||||
LEFT JOIN `'._DB_PREFIX_.'currency` cu ON (cu.`id_currency` = a.`id_currency`)
|
||||
@@ -113,6 +118,9 @@ class AdminOrdersControllerCore extends AdminController
|
||||
foreach ($all_order_sources as $source) {
|
||||
$this->all_order_sources[$source['source']] = $source['source'];
|
||||
}
|
||||
foreach (Source::getSourcesUsedInOrders((int)$this->context->language->id) as $bookingSource) {
|
||||
$this->bookingSourcesArray[$bookingSource['id_source']] = $bookingSource['name'];
|
||||
}
|
||||
|
||||
$hotelsArray = HotelBranchInformation::getProfileAccessedHotels($this->context->employee->id_profile, 1);
|
||||
foreach ($hotelsArray as $hotel) {
|
||||
@@ -272,6 +280,16 @@ class AdminOrdersControllerCore extends AdminController
|
||||
'optional' => true,
|
||||
'visible_default' => true
|
||||
),
|
||||
'booking_source_name' => array(
|
||||
'title' => $this->l('Booking Source'),
|
||||
'type' => 'select',
|
||||
'filter_key' => 'a!id_source',
|
||||
'list' => $this->bookingSourcesArray,
|
||||
'orderby' => false,
|
||||
'callback' => 'formatBookingSource',
|
||||
'optional' => true,
|
||||
'visible_default' => true
|
||||
),
|
||||
'osname' => array(
|
||||
'title' => $this->l('Status'),
|
||||
'type' => 'select',
|
||||
@@ -359,6 +377,26 @@ class AdminOrdersControllerCore extends AdminController
|
||||
return Tools::displayPrice($echo, (int)$idCurrency);
|
||||
}
|
||||
|
||||
/**
|
||||
* fields_list callback for the Booking Source column — shows the Booking Source name and,
|
||||
* only for the built-in "Direct Website" source, a link to the storefront alongside it.
|
||||
*/
|
||||
public static function formatBookingSource($echo, $row)
|
||||
{
|
||||
if (!$echo) {
|
||||
return '--';
|
||||
}
|
||||
|
||||
$html = Tools::safeOutput($echo);
|
||||
|
||||
if (isset($row['booking_source_code']) && $row['booking_source_code'] === 'DIRECT_WEBSITE') {
|
||||
$title = Translate::getAdminTranslation('Visit website', 'AdminOrders', true);
|
||||
$html .= ' <a href="'.Context::getContext()->link->getBaseLink().'" target="_blank" title="'.$title.'"><i class="icon-external-link"></i></a>';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function initPageHeaderToolbar()
|
||||
{
|
||||
if (empty($this->display)) {
|
||||
|
||||
709
controllers/admin/AdminSourcesController.php
Normal file
709
controllers/admin/AdminSourcesController.php
Normal file
@@ -0,0 +1,709 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License version 3.0
|
||||
* that is bundled with this package in the file LICENSE.md
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/license/osl-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 support@qloapps.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade QloApps to newer
|
||||
* versions in the future. If you wish to customize QloApps for your needs
|
||||
* please refer to https://store.webkul.com/customisation-guidelines for more information.
|
||||
*
|
||||
* @author Webkul IN
|
||||
* @copyright Since 2010 Webkul
|
||||
* @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0
|
||||
*/
|
||||
|
||||
|
||||
class AdminSourcesControllerCore extends AdminController
|
||||
{
|
||||
protected $position_identifier = 'id_source_type';
|
||||
|
||||
/** @var int Total order count, cached once per list render for the Orders % column */
|
||||
protected $ordersTotal = 0;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->bootstrap = true;
|
||||
$this->table = 'business_source';
|
||||
$this->className = 'BusinessSource';
|
||||
$this->identifier = 'id_source_type';
|
||||
$this->list_id = 'business_source';
|
||||
$this->lang = true;
|
||||
$this->deleted = false;
|
||||
$this->_defaultOrderBy = 'position';
|
||||
$this->_defaultOrderWay = 'ASC';
|
||||
$this->context = Context::getContext();
|
||||
|
||||
$this->bulk_actions = array(
|
||||
'delete' => array(
|
||||
'text' => $this->l('Delete selected'),
|
||||
'icon' => 'icon-trash',
|
||||
'confirm' => $this->l('Delete selected items?')
|
||||
)
|
||||
);
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function setMedia()
|
||||
{
|
||||
parent::setMedia();
|
||||
|
||||
$this->addJS(_PS_JS_DIR_.'admin/sources.js');
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
if (Tools::isSubmit('viewbusiness_source')
|
||||
|| Tools::isSubmit('submitFiltersource')
|
||||
|| Tools::isSubmit('submitResetsource')
|
||||
|| Tools::getValue('sourceOrderby')
|
||||
|| Tools::getValue('sourceOrderway')
|
||||
) {
|
||||
$this->list_id = 'source';
|
||||
}
|
||||
|
||||
$idSourceType = (int) Tools::getValue('id_source_type');
|
||||
|
||||
if ($idSourceType && Tools::getValue('viewbusiness_source')) {
|
||||
self::$currentIndex .= '&id_source_type=' . $idSourceType . '&viewbusiness_source';
|
||||
$this->className = 'Source';
|
||||
}
|
||||
|
||||
if (Tools::isSubmit('addsource') || Tools::isSubmit('addbusiness_source')) {
|
||||
$this->display = 'add';
|
||||
}
|
||||
if (Tools::isSubmit('updatesource') || Tools::isSubmit('updatebusiness_source')) {
|
||||
$this->display = 'edit';
|
||||
}
|
||||
if (Tools::isSubmit('submitAddsource') || Tools::isSubmit('submitAddsourceAndStay')) {
|
||||
$this->display = Tools::getValue('id_source') ? 'edit' : 'add';
|
||||
}
|
||||
if (Tools::isSubmit('submitAddbusiness_source') || Tools::isSubmit('submitAddbusiness_sourceAndStay')) {
|
||||
$this->display = Tools::getValue('id_source_type') ? 'edit' : 'add';
|
||||
}
|
||||
|
||||
|
||||
return parent::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AdminController::initPageHeaderToolbar()
|
||||
*/
|
||||
public function initPageHeaderToolbar()
|
||||
{
|
||||
if (empty($this->display)) {
|
||||
$this->page_header_toolbar_btn['new_business_source'] = array(
|
||||
'href' => self::$currentIndex.'&addbusiness_source&token='.$this->token,
|
||||
'desc' => $this->l('Add new Business Source', null, null, false),
|
||||
'icon' => 'process-icon-new'
|
||||
);
|
||||
} elseif ($this->display == 'view') {
|
||||
$idSourceType = (int)Tools::getValue('id_source_type');
|
||||
if ($idSourceType) {
|
||||
$this->page_header_toolbar_btn['new_source'] = array(
|
||||
'href' => self::$currentIndex.'&addsource&id_source_type='.$idSourceType.'&token='.$this->token,
|
||||
'desc' => $this->l('Add new Booking Source', null, null, false),
|
||||
'icon' => 'process-icon-new'
|
||||
);
|
||||
$this->page_header_toolbar_btn['back_to_business'] = array(
|
||||
'href' => self::$currentIndex.'&token='.$this->token,
|
||||
'desc' => $this->l('Back To Business Source', null, null, false),
|
||||
'icon' => 'process-icon-back'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unset($this->toolbar_btn['back']);
|
||||
parent::initPageHeaderToolbar();
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected function initBusinessSourcesList()
|
||||
{
|
||||
$this->fields_list = array(
|
||||
'id_source_type' => array(
|
||||
'title' => $this->l('ID'),
|
||||
'align' => 'text-center',
|
||||
'class' => 'fixed-width-xs'
|
||||
),
|
||||
'name' => array(
|
||||
'title' => $this->l('Name'),
|
||||
'width' => 'auto',
|
||||
'filter_key' => 'b!name'
|
||||
),
|
||||
'source_type_code' => array(
|
||||
'title' => $this->l('Code'),
|
||||
'align' => 'text-center'
|
||||
),
|
||||
'position' => array(
|
||||
'title' => $this->l('Position'),
|
||||
'filter_key' => 'a!position',
|
||||
'align' => 'text-center',
|
||||
'class' => 'fixed-width-xs',
|
||||
'position' => 'position'
|
||||
),
|
||||
'orders_count' => array(
|
||||
'title' => $this->l('Orders'),
|
||||
'align' => 'text-center',
|
||||
'orderby' => false,
|
||||
'search' => false,
|
||||
'callback' => 'formatOrdersPercentage',
|
||||
),
|
||||
'active' => array(
|
||||
'title' => $this->l('Enabled'),
|
||||
'active' => 'status',
|
||||
'type' => 'bool',
|
||||
'align' => 'text-center',
|
||||
'class' => 'fixed-width-xs',
|
||||
'orderby' => false
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
protected function initSourcesList()
|
||||
{
|
||||
$this->fields_list = array(
|
||||
'id_source' => array(
|
||||
'title' => $this->l('ID'),
|
||||
'align' => 'text-center',
|
||||
'class' => 'fixed-width-xs'
|
||||
),
|
||||
'name' => array(
|
||||
'title' => $this->l('Name'),
|
||||
'width' => 'auto',
|
||||
'filter_key' => 'b!name'
|
||||
),
|
||||
'source_type_name' => array(
|
||||
'title' => $this->l('Business Source'),
|
||||
'orderby' => false,
|
||||
'search' => false,
|
||||
),
|
||||
'source_code' => array(
|
||||
'title' => $this->l('Code'),
|
||||
'align' => 'text-center'
|
||||
),
|
||||
'position' => array(
|
||||
'title' => $this->l('Position'),
|
||||
'filter_key' => 'a!position',
|
||||
'align' => 'text-center',
|
||||
'class' => 'fixed-width-xs',
|
||||
'position' => 'position'
|
||||
),
|
||||
'orders_count' => array(
|
||||
'title' => $this->l('Orders'),
|
||||
'align' => 'text-center',
|
||||
'orderby' => false,
|
||||
'search' => false,
|
||||
'callback' => 'formatOrdersPercentage',
|
||||
),
|
||||
'active' => array(
|
||||
'title' => $this->l('Enabled'),
|
||||
'active' => 'status',
|
||||
'type' => 'bool',
|
||||
'align' => 'text-center',
|
||||
'class' => 'fixed-width-xs',
|
||||
'orderby' => false
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function renderList()
|
||||
{
|
||||
$this->addRowAction('view');
|
||||
$this->addRowAction('edit');
|
||||
$this->addRowAction('delete');
|
||||
|
||||
$this->addRowActionSkipList('delete', BusinessSource::getUnremovableIds());
|
||||
$this->_where = 'AND a.`deleted` = 0';
|
||||
$this->_select = '(SELECT COUNT(*) FROM `'._DB_PREFIX_.'orders` o
|
||||
INNER JOIN `'._DB_PREFIX_.'source` s ON s.`id_source` = o.`id_source`
|
||||
WHERE s.`id_source_type` = a.`id_source_type`) AS `orders_count`';
|
||||
$this->ordersTotal = Source::getTotalOrderCount();
|
||||
$this->initBusinessSourcesList();
|
||||
$this->toolbar_title = $this->l('Business Source');
|
||||
|
||||
return parent::renderList();
|
||||
}
|
||||
|
||||
public function renderView()
|
||||
{
|
||||
$idSourceType = (int)Tools::getValue('id_source_type');
|
||||
$objBusinessSource = new BusinessSource($idSourceType, (int)$this->context->language->id);
|
||||
if (!Validate::isLoadedObject($objBusinessSource)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->addRowAction('edit');
|
||||
$this->addRowAction('merge');
|
||||
$this->addRowAction('delete');
|
||||
$this->addRowActionSkipList('delete', Source::getUnremovableIds());
|
||||
|
||||
$this->table = 'source';
|
||||
$this->className = 'Source';
|
||||
$this->identifier = 'id_source';
|
||||
$this->list_id = 'source';
|
||||
$this->_select = 'bsl.`name` AS `source_type_name`,
|
||||
(SELECT COUNT(*) FROM `'._DB_PREFIX_.'orders` o WHERE o.`id_source` = a.`id_source`) AS `orders_count`';
|
||||
$this->ordersTotal = $objBusinessSource->getOrderCount();
|
||||
$this->_join = 'LEFT JOIN `'._DB_PREFIX_.'business_source` bs ON (bs.`id_source_type` = a.`id_source_type`)';
|
||||
$this->_join .= 'LEFT JOIN `'._DB_PREFIX_.'business_source_lang` bsl ON (bsl.`id_source_type` = bs.`id_source_type` AND bsl.`id_lang` = '.(int)$this->context->language->id.')';
|
||||
$this->_where = 'AND a.`deleted` = 0 AND a.`id_source_type` = '.(int)$objBusinessSource->id;
|
||||
$this->initSourcesList();
|
||||
|
||||
$this->toolbar_title = sprintf($this->l('Booking Source - %s'),$objBusinessSource->name);
|
||||
$this->processFilter();
|
||||
return parent::renderList();
|
||||
}
|
||||
|
||||
public function renderForm()
|
||||
{
|
||||
if (Tools::isSubmit('updatesource')
|
||||
|| Tools::isSubmit('addsource')
|
||||
|| Tools::isSubmit('submitAddsource')
|
||||
|| Tools::isSubmit('submitAddsourceAndStay')
|
||||
) {
|
||||
return $this->renderSourceForm();
|
||||
}
|
||||
|
||||
return $this->renderBusinessSourceForm();
|
||||
}
|
||||
|
||||
protected function renderBusinessSourceForm()
|
||||
{
|
||||
if (!($objBusinessSource = $this->loadObject(true))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fields_form = array(
|
||||
'legend' => array(
|
||||
'title' => $this->l('Business Source'),
|
||||
'icon' => 'icon-tags'
|
||||
),
|
||||
'input' => array(
|
||||
array(
|
||||
'type' => 'text',
|
||||
'label' => $this->l('Name'),
|
||||
'name' => 'name',
|
||||
'lang' => true,
|
||||
'required' => true,
|
||||
'hint' => $this->l('Invalid characters:').' <>;=#{}'
|
||||
),
|
||||
array(
|
||||
'type' => 'text',
|
||||
'label' => $this->l('Code'),
|
||||
'name' => 'source_type_code',
|
||||
'required' => true,
|
||||
'hint' => $this->l('A short unique machine code, e.g. "OTA". Letters, numbers, underscores and hyphens only.')
|
||||
),
|
||||
array(
|
||||
'type' => 'switch',
|
||||
'label' => $this->l('Enabled'),
|
||||
'name' => 'active',
|
||||
'required' => false,
|
||||
'class' => 't',
|
||||
'is_bool' => true,
|
||||
'values' => array(
|
||||
array('id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled')),
|
||||
array('id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled')),
|
||||
)
|
||||
),
|
||||
),
|
||||
'submit' => array(
|
||||
'title' => $this->l('Save'),
|
||||
'name' => 'submitAddbusiness_source'
|
||||
),
|
||||
'buttons' => array(
|
||||
'save-and-stay' => array(
|
||||
'title' => $this->l('Save and stay'),
|
||||
'name' => 'submitAddbusiness_sourceAndStay',
|
||||
'type' => 'submit',
|
||||
'class' => 'btn btn-default pull-right',
|
||||
'icon' => 'process-icon-save',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return parent::renderForm();
|
||||
}
|
||||
|
||||
protected function renderSourceForm()
|
||||
{
|
||||
$this->table = 'source';
|
||||
$this->className = 'Source';
|
||||
$this->identifier = 'id_source';
|
||||
$this->object = null;
|
||||
|
||||
if (!($objSource = $this->loadObject(true))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$businessSources = BusinessSource::getActiveList((int)$this->context->language->id);
|
||||
|
||||
$this->fields_form = array(
|
||||
'legend' => array(
|
||||
'title' => $this->l('Booking Source'),
|
||||
'icon' => 'icon-tags'
|
||||
),
|
||||
'input' => array(
|
||||
array(
|
||||
'type' => 'text',
|
||||
'label' => $this->l('Name'),
|
||||
'name' => 'name',
|
||||
'lang' => true,
|
||||
'required' => true,
|
||||
'hint' => $this->l('Invalid characters:').' <>;=#{}'
|
||||
),
|
||||
array(
|
||||
'type' => 'select',
|
||||
'label' => $this->l('Business Source'),
|
||||
'name' => 'id_source_type',
|
||||
'required' => true,
|
||||
'options' => array(
|
||||
'query' => $businessSources,
|
||||
'id' => 'id_source_type',
|
||||
'name' => 'name',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'type' => 'text',
|
||||
'label' => $this->l('Source Code'),
|
||||
'name' => 'source_code',
|
||||
'required' => true,
|
||||
'hint' => $this->l('A short unique machine code, e.g. "BOOKING_COM". Letters, numbers, underscores and hyphens only.')
|
||||
),
|
||||
array(
|
||||
'type' => 'switch',
|
||||
'label' => $this->l('Enabled'),
|
||||
'name' => 'active',
|
||||
'required' => false,
|
||||
'class' => 't',
|
||||
'is_bool' => true,
|
||||
'values' => array(
|
||||
array('id' => 'active_on', 'value' => 1, 'label' => $this->l('Enabled')),
|
||||
array('id' => 'active_off', 'value' => 0, 'label' => $this->l('Disabled')),
|
||||
)
|
||||
),
|
||||
),
|
||||
'submit' => array(
|
||||
'title' => $this->l('Save'),
|
||||
'name' => 'submitAddsource'
|
||||
),
|
||||
'buttons' => array(
|
||||
'save-and-stay' => array(
|
||||
'title' => $this->l('Save and stay'),
|
||||
'name' => 'submitAddsourceAndStay',
|
||||
'type' => 'submit',
|
||||
'class' => 'btn btn-default pull-right',
|
||||
'icon' => 'process-icon-save',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return parent::renderForm();
|
||||
}
|
||||
|
||||
|
||||
public function postProcess()
|
||||
{
|
||||
if (Tools::isSubmit('submitAddsource') || Tools::isSubmit('submitAddsourceAndStay')) {
|
||||
return $this->postProcessSource();
|
||||
} elseif (Tools::isSubmit('submitMergeSource')) {
|
||||
return $this->postProcessMergeSource();
|
||||
} elseif (Tools::isSubmit('deletesource')) {
|
||||
$objSource = new Source((int)Tools::getValue('id_source'));
|
||||
if (!$objSource->isRemovable()) {
|
||||
$this->errors[] = $this->l('For security reasons, you cannot delete a built-in Booking Source.');
|
||||
} elseif (!$objSource->delete()) {
|
||||
$this->errors[] = Tools::displayError('An error occurred while deleting the Booking Source.');
|
||||
} else {
|
||||
Tools::redirectAdmin(self::$currentIndex.'&viewbusiness_source&id_source_type='.(int)$objSource->id_source_type.'&conf=1&token='.$this->token);
|
||||
}
|
||||
} else if(Tools::isSubmit('submitBulkenableSelectionsource')){
|
||||
$idSourceType = (int)Tools::getValue('id_source_type');
|
||||
$this->className = 'Source';
|
||||
$this->table = 'source';
|
||||
$this->boxes = Tools::getValue('sourceBox');
|
||||
parent::processBulkEnableSelection();
|
||||
$this->redirect_after = self::$currentIndex.'&viewbusiness_source&id_source_type='.(int)$idSourceType.'&token='.$this->token;
|
||||
} else if(Tools::isSubmit('submitBulkdisableSelectionsource')){
|
||||
$idSourceType = (int)Tools::getValue('id_source_type');
|
||||
$this->className = 'Source';
|
||||
$this->table = 'source';
|
||||
$this->boxes = Tools::getValue('sourceBox');
|
||||
parent::processBulkDisableSelection();
|
||||
$this->redirect_after = self::$currentIndex.'&viewbusiness_source&id_source_type='.(int)$idSourceType.'&token='.$this->token;
|
||||
} elseif (Tools::isSubmit('submitBulkdeletesource')) {
|
||||
$idSourceType = 0;
|
||||
foreach (Tools::getValue('sourceBox') as $selection) {
|
||||
$objSource = new Source((int)$selection);
|
||||
$idSourceType = $objSource->id_source_type;
|
||||
if (!$objSource->isRemovable()) {
|
||||
$this->errors[] = $this->l('For security reasons, you cannot delete a built-in Booking Source.');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!count($this->errors)) {
|
||||
$this->className = 'Source';
|
||||
$this->table = 'source';
|
||||
$this->boxes = Tools::getValue('sourceBox');
|
||||
parent::processBulkDelete();
|
||||
$this->redirect_after = self::$currentIndex.'&viewbusiness_source&id_source_type='.(int)$idSourceType.'&conf=1&token='.$this->token;
|
||||
}
|
||||
} elseif (Tools::isSubmit('submitAddbusiness_source') || Tools::isSubmit('submitAddbusiness_sourceAndStay')) {
|
||||
return $this->postProcessBusinessSource();
|
||||
} elseif (Tools::isSubmit('delete'.$this->table)) {
|
||||
$objBusinessSource = new BusinessSource((int)Tools::getValue('id_source_type'));
|
||||
if (!$objBusinessSource->isRemovable()) {
|
||||
$this->errors[] = $this->l('For security reasons, you cannot delete a built-in Business Source.');
|
||||
} else {
|
||||
return parent::postProcess();
|
||||
}
|
||||
} elseif (Tools::isSubmit('submitBulkdelete'.$this->table)) {
|
||||
foreach (Tools::getValue($this->table.'Box') as $selection) {
|
||||
$objBusinessSource = new BusinessSource((int)$selection);
|
||||
if (!$objBusinessSource->isRemovable()) {
|
||||
$this->errors[] = $this->l('For security reasons, you cannot delete a built-in Business Source.');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!count($this->errors)) {
|
||||
return parent::postProcess();
|
||||
}
|
||||
} else {
|
||||
return parent::postProcess();
|
||||
}
|
||||
}
|
||||
|
||||
protected function postProcessSource()
|
||||
{
|
||||
$idSource = (int)Tools::getValue('id_source');
|
||||
$idSourceType = (int)Tools::getValue('id_source_type');
|
||||
$sourceCode = trim(Tools::getValue('source_code'));
|
||||
|
||||
$defaultLangId = Configuration::get('PS_LANG_DEFAULT');
|
||||
$objDefaultLanguage = Language::getLanguage((int) $defaultLangId);
|
||||
$languages = Language::getLanguages(false);
|
||||
if (!trim(Tools::getValue('name_'.$defaultLangId))) {
|
||||
$this->errors[] = $this->l('Name is required at least in ').
|
||||
$objDefaultLanguage['name'];
|
||||
} else {
|
||||
foreach ($languages as $lang) {
|
||||
if (trim(Tools::getValue('name_'.$lang['id_lang']))) {
|
||||
if (!Validate::isGenericName(Tools::getValue('name_'.$lang['id_lang']))) {
|
||||
$this->errors[] = $this->l('Invalid name in ').$lang['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$objBusinessSource = new BusinessSource($idSourceType);
|
||||
if (!Validate::isLoadedObject($objBusinessSource) || $objBusinessSource->deleted) {
|
||||
$this->errors[] = $this->l('Please select a valid Business Source.');
|
||||
}
|
||||
|
||||
if (!$sourceCode || !Validate::isModuleName($sourceCode)) {
|
||||
$this->errors[] = $this->l('Source Code is invalid. Only letters, numbers, underscores and hyphens are allowed.');
|
||||
} elseif (Source::codeExists($sourceCode, $idSource)) {
|
||||
$this->errors[] = $this->l('This Source Code is already used by another Booking Source.');
|
||||
}
|
||||
|
||||
if (count($this->errors)) {
|
||||
$this->display = $idSource ? 'edit' : 'add';
|
||||
return false;
|
||||
}
|
||||
|
||||
$objSource = new Source($idSource);
|
||||
$objSource->id_source_type = $idSourceType;
|
||||
$objSource->source_code = $sourceCode;
|
||||
$objSource->active = (int)Tools::getValue('active');
|
||||
$objSource->name = array();
|
||||
foreach (Language::getIDs(false) as $idLang) {
|
||||
$objSource->name[$idLang] = Tools::getValue('name_'.$idLang);
|
||||
}
|
||||
|
||||
if (!$objSource->save()) {
|
||||
$this->errors[] = Tools::displayError('An error occurred while saving the Booking Source.');
|
||||
$this->display = $idSource ? 'edit' : 'add';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Tools::isSubmit('submitAddsourceAndStay')) {
|
||||
Tools::redirectAdmin(self::$currentIndex.'&updatesource&id_source='.$objSource->id.'&conf='.($idSource ? 4 : 3).'&token='.$this->token);
|
||||
}
|
||||
|
||||
Tools::redirectAdmin(self::$currentIndex.'&viewbusiness_source&id_source_type='.$idSourceType.'&conf='.($idSource ? 4 : 3).'&token='.$this->token);
|
||||
}
|
||||
|
||||
protected function postProcessMergeSource()
|
||||
{
|
||||
$idSourceType = (int)Tools::getValue('id_source_type');
|
||||
$idCurrentSource = (int)Tools::getValue('merge_current_source');
|
||||
$idTargetSource = (int)Tools::getValue('merge_target_source');
|
||||
|
||||
$objCurrent = new Source($idCurrentSource);
|
||||
$objTarget = new Source($idTargetSource);
|
||||
|
||||
if (!Validate::isLoadedObject($objCurrent) || !Validate::isLoadedObject($objTarget)
|
||||
|| (int)$objCurrent->id_source_type !== $idSourceType || (int)$objTarget->id_source_type !== $idSourceType
|
||||
) {
|
||||
$this->errors[] = $this->l('Please select valid Current and Target Booking Sources.');
|
||||
} elseif ($idCurrentSource === $idTargetSource) {
|
||||
$this->errors[] = $this->l('Current and Target Booking Source cannot be the same.');
|
||||
} else {
|
||||
$objCurrent->mergeOrdersInto($idTargetSource);
|
||||
}
|
||||
|
||||
if (!count($this->errors)) {
|
||||
Tools::redirectAdmin(self::$currentIndex.'&viewbusiness_source&id_source_type='.$idSourceType.'&conf=4&token='.$this->token);
|
||||
}
|
||||
}
|
||||
|
||||
protected function postProcessBusinessSource()
|
||||
{
|
||||
$idSourceType = (int)Tools::getValue('id_source_type');
|
||||
$sourceTypeCode = trim(Tools::getValue('source_type_code'));
|
||||
|
||||
$defaultLangId = Configuration::get('PS_LANG_DEFAULT');
|
||||
$objDefaultLanguage = Language::getLanguage((int) $defaultLangId);
|
||||
$languages = Language::getLanguages(false);
|
||||
if (!trim(Tools::getValue('name_'.$defaultLangId))) {
|
||||
$this->errors[] = $this->l('Name is required at least in ').
|
||||
$objDefaultLanguage['name'];
|
||||
} else {
|
||||
foreach ($languages as $lang) {
|
||||
if (trim(Tools::getValue('name_'.$lang['id_lang']))) {
|
||||
if (!Validate::isGenericName(Tools::getValue('name_'.$lang['id_lang']))) {
|
||||
$this->errors[] = $this->l('Invalid name in ').$lang['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$sourceTypeCode || !Validate::isModuleName($sourceTypeCode)) {
|
||||
$this->errors[] = $this->l('Code is invalid. Only letters, numbers, underscores and hyphens are allowed.');
|
||||
} elseif (BusinessSource::codeExists($sourceTypeCode, $idSourceType)) {
|
||||
$this->errors[] = $this->l('This Code is already used by another Business Source.');
|
||||
}
|
||||
|
||||
if (count($this->errors)) {
|
||||
$this->display = $idSourceType ? 'edit' : 'add';
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::postProcess();
|
||||
}
|
||||
|
||||
public function formatOrdersPercentage($count, $row)
|
||||
{
|
||||
$percentage = $this->ordersTotal ? round(((int)$count / $this->ordersTotal) * 100, 1) : 0;
|
||||
return $percentage.'%';
|
||||
}
|
||||
|
||||
public function displayMergeLink($token, $id, $name = null)
|
||||
{
|
||||
$idSourceType = (int) Tools::getValue('id_source_type');
|
||||
|
||||
return '<a href="#"
|
||||
class="merge-source-btn"
|
||||
title="' . $this->l('Merge') . '"
|
||||
data-id-source="' . (int) $id . '"
|
||||
data-id-source-type="' . $idSourceType . '"
|
||||
data-ajax-url="' . self::$currentIndex . '&token=' . ($token ?: $this->token) . '">
|
||||
<i class="icon-random"></i> ' . $this->l('Merge') . '
|
||||
</a>';
|
||||
}
|
||||
|
||||
public function ajaxProcessInitMergeSourceModal()
|
||||
{
|
||||
$response = array('hasError' => 1);
|
||||
|
||||
if ($this->tabAccess['edit'] === 1) {
|
||||
$idSourceType = (int)Tools::getValue('id_source_type');
|
||||
$idSource = (int)Tools::getValue('id_source');
|
||||
$objSource = new Source($idSource);
|
||||
|
||||
if (Validate::isLoadedObject($objSource) && (int)$objSource->id_source_type === $idSourceType) {
|
||||
$this->context->smarty->assign(array(
|
||||
'sources' => Source::getActiveListForType($idSourceType, (int)$this->context->language->id),
|
||||
'id_current_source' => $idSource,
|
||||
'id_source_type' => $idSourceType,
|
||||
'current_index' => self::$currentIndex,
|
||||
'token' => $this->token,
|
||||
));
|
||||
|
||||
$this->context->smarty->assign(array(
|
||||
'modal_id' => 'merge_source_modal',
|
||||
'modal_class' => 'modal-md',
|
||||
'modal_title' => $this->l('Merge Booking Source'),
|
||||
'modal_content' => $this->context->smarty->fetch('controllers/sources/modals/_merge_source_form.tpl'),
|
||||
));
|
||||
|
||||
$response['hasError'] = 0;
|
||||
$response['modalHtml'] = $this->context->smarty->fetch('modal.tpl');
|
||||
}
|
||||
}
|
||||
|
||||
die(Tools::jsonEncode($response));
|
||||
}
|
||||
|
||||
protected function filterToField($key, $filter)
|
||||
{
|
||||
if ($this->table == 'source') {
|
||||
$this->initSourcesList();
|
||||
} else {
|
||||
$this->initBusinessSourcesList();
|
||||
}
|
||||
|
||||
return parent::filterToField($key, $filter);
|
||||
}
|
||||
|
||||
public function ajaxProcessUpdatePositions()
|
||||
{
|
||||
if ($this->tabAccess['edit'] !== 1) {
|
||||
die(json_encode(array('hasError' => true, 'errors' => $this->l('You do not have permission to edit this.'))));
|
||||
}
|
||||
|
||||
$way = (int)Tools::getValue('way');
|
||||
$id = (int)Tools::getValue('id');
|
||||
|
||||
if ($positions = Tools::getValue('source')) {
|
||||
$className = 'Source';
|
||||
} elseif ($positions = Tools::getValue('source_type')) {
|
||||
$className = 'BusinessSource';
|
||||
} else {
|
||||
die(json_encode(array('hasError' => true, 'errors' => 'Unknown table for position update.')));
|
||||
}
|
||||
|
||||
foreach ($positions as $position => $value) {
|
||||
$pos = explode('_', $value);
|
||||
|
||||
if (isset($pos[2]) && (int)$pos[2] === $id) {
|
||||
if ($object = new $className((int)$pos[2])) {
|
||||
if (isset($position) && $object->updatePosition($way, $position)) {
|
||||
echo 'ok position '.(int)$position.' for '.$className.' '.$id;
|
||||
} else {
|
||||
echo '{"hasError" : true, "errors" : "Can not update tab '.(int)$id.' to position '.(int)$position.' "}';
|
||||
}
|
||||
} else {
|
||||
echo json_encode(array(
|
||||
'hasError' => true,
|
||||
'errors' => 'Can not update '.$className.' '.$id.' to position '.(int)$position,
|
||||
));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1174,6 +1174,7 @@ CREATE TABLE `PREFIX_orders` (
|
||||
`invoice_date` datetime NOT NULL,
|
||||
`delivery_date` datetime NOT NULL,
|
||||
`source` varchar(255) DEFAULT NULL,
|
||||
`id_source` int(10) unsigned DEFAULT NULL,
|
||||
`valid` int(1) unsigned NOT NULL DEFAULT '0',
|
||||
`is_advance_payment` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`advance_paid_amount` decimal(20,6) NOT NULL DEFAULT '0.00',
|
||||
@@ -1193,6 +1194,7 @@ CREATE TABLE `PREFIX_orders` (
|
||||
KEY `id_shop_group` (`id_shop_group`),
|
||||
KEY (`current_state`),
|
||||
KEY `id_shop` (`id_shop`),
|
||||
KEY `id_source` (`id_source`),
|
||||
INDEX `date_add`(`date_add`)
|
||||
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 COLLATION;
|
||||
|
||||
@@ -1879,6 +1881,48 @@ CREATE TABLE `PREFIX_search_word` (
|
||||
UNIQUE KEY `id_lang` (`id_lang`,`id_shop`, `word`)
|
||||
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 COLLATION;
|
||||
|
||||
CREATE TABLE `PREFIX_business_source` (
|
||||
`id_source_type` int(10) unsigned NOT NULL auto_increment,
|
||||
`source_type_code` varchar(64) NOT NULL,
|
||||
`position` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`unremovable` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`active` tinyint(1) UNSIGNED NOT NULL DEFAULT '1',
|
||||
`deleted` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`date_add` datetime NOT NULL,
|
||||
`date_upd` datetime NOT NULL,
|
||||
PRIMARY KEY (`id_source_type`),
|
||||
UNIQUE KEY `source_type_code` (`source_type_code`)
|
||||
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 COLLATION;
|
||||
|
||||
CREATE TABLE `PREFIX_business_source_lang` (
|
||||
`id_source_type` int(10) unsigned NOT NULL,
|
||||
`id_lang` int(10) unsigned NOT NULL,
|
||||
`name` varchar(64) NOT NULL,
|
||||
PRIMARY KEY (`id_source_type`,`id_lang`)
|
||||
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 COLLATION;
|
||||
|
||||
CREATE TABLE `PREFIX_source` (
|
||||
`id_source` int(10) unsigned NOT NULL auto_increment,
|
||||
`id_source_type` int(10) unsigned NOT NULL,
|
||||
`source_code` varchar(64) NOT NULL,
|
||||
`position` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`unremovable` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`active` tinyint(1) UNSIGNED NOT NULL DEFAULT '1',
|
||||
`deleted` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`date_add` datetime NOT NULL,
|
||||
`date_upd` datetime NOT NULL,
|
||||
PRIMARY KEY (`id_source`),
|
||||
UNIQUE KEY `source_code` (`source_code`),
|
||||
KEY `id_source_type` (`id_source_type`)
|
||||
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 COLLATION;
|
||||
|
||||
CREATE TABLE `PREFIX_source_lang` (
|
||||
`id_source` int(10) unsigned NOT NULL,
|
||||
`id_lang` int(10) unsigned NOT NULL,
|
||||
`name` varchar(64) NOT NULL,
|
||||
PRIMARY KEY (`id_source`,`id_lang`)
|
||||
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 COLLATION;
|
||||
|
||||
CREATE TABLE `PREFIX_specific_price` (
|
||||
`id_specific_price` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`id_specific_price_rule` INT(11) UNSIGNED NOT NULL,
|
||||
|
||||
21
install/data/xml/business_source.xml
Normal file
21
install/data/xml/business_source.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<entity_business_source>
|
||||
<fields id="name" class="BusinessSource">
|
||||
<field name="source_type_code"/>
|
||||
<field name="position"/>
|
||||
<field name="unremovable"/>
|
||||
<field name="active"/>
|
||||
</fields>
|
||||
<entities>
|
||||
<business_source id="Direct" source_type_code="DIRECT" position="1" unremovable="1" active="1">
|
||||
</business_source>
|
||||
<business_source id="OTA" source_type_code="OTA" position="2" unremovable="1" active="1">
|
||||
</business_source>
|
||||
<business_source id="Corporate" source_type_code="CORPORATE" position="3" unremovable="1" active="1">
|
||||
</business_source>
|
||||
<business_source id="Travel_Agent" source_type_code="TRAVEL_AGENT" position="4" unremovable="1" active="1">
|
||||
</business_source>
|
||||
<business_source id="Group" source_type_code="GROUP" position="5" unremovable="1" active="1">
|
||||
</business_source>
|
||||
</entities>
|
||||
</entity_business_source>
|
||||
34
install/data/xml/source.xml
Normal file
34
install/data/xml/source.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<entity_source>
|
||||
<fields id="name" class="Source">
|
||||
<field name="id_source_type" relation="business_source"/>
|
||||
<field name="source_code"/>
|
||||
<field name="position"/>
|
||||
<field name="unremovable"/>
|
||||
<field name="active"/>
|
||||
</fields>
|
||||
<entities>
|
||||
<source id="Direct_Website" id_source_type="Direct" source_code="DIRECT_WEBSITE" position="1" unremovable="1" active="1">
|
||||
</source>
|
||||
<source id="Walk_in" id_source_type="Direct" source_code="WALKIN" position="2" unremovable="1" active="1">
|
||||
</source>
|
||||
<source id="Phone" id_source_type="Direct" source_code="PHONE" position="3" unremovable="0" active="1">
|
||||
</source>
|
||||
<source id="Email" id_source_type="Direct" source_code="EMAIL" position="4" unremovable="0" active="1">
|
||||
</source>
|
||||
<source id="Social_Media" id_source_type="Direct" source_code="SOCIAL_MEDIA" position="0" unremovable="1" active="1">
|
||||
</source>
|
||||
<source id="WhatsApp" id_source_type="Direct" source_code="WHATSAPP" position="6" unremovable="0" active="1">
|
||||
</source>
|
||||
<source id="Booking_com" id_source_type="OTA" source_code="BOOKING_COM" position="7" unremovable="0" active="1">
|
||||
</source>
|
||||
<source id="Expedia" id_source_type="OTA" source_code="EXPEDIA" position="8" unremovable="0" active="1">
|
||||
</source>
|
||||
<source id="GoMMT" id_source_type="OTA" source_code="GOMMT" position="9" unremovable="0" active="1">
|
||||
</source>
|
||||
<source id="Agoda" id_source_type="OTA" source_code="AGODA" position="10" unremovable="0" active="1">
|
||||
</source>
|
||||
<source id="Airbnb" id_source_type="OTA" source_code="AIRBNB" position="11" unremovable="0" active="1">
|
||||
</source>
|
||||
</entities>
|
||||
</entity_source>
|
||||
@@ -117,6 +117,9 @@
|
||||
<tab id="Statuses" id_parent="Orders" active="1" hide_host_mode="0">
|
||||
<class_name>AdminStatuses</class_name>
|
||||
</tab>
|
||||
<tab id="Sources" id_parent="Orders" active="1" hide_host_mode="0">
|
||||
<class_name>AdminSources</class_name>
|
||||
</tab>
|
||||
<tab id="Order_Messages" id_parent="Orders" active="1" hide_host_mode="0">
|
||||
<class_name>AdminOrderMessage</class_name>
|
||||
</tab>
|
||||
|
||||
18
install/langs/en/data/business_source.xml
Normal file
18
install/langs/en/data/business_source.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
<entity_business_source>
|
||||
<business_source id="Direct">
|
||||
<name>Direct</name>
|
||||
</business_source>
|
||||
<business_source id="OTA">
|
||||
<name>OTA</name>
|
||||
</business_source>
|
||||
<business_source id="Corporate">
|
||||
<name>Corporate</name>
|
||||
</business_source>
|
||||
<business_source id="Travel_Agent">
|
||||
<name>Travel Agent</name>
|
||||
</business_source>
|
||||
<business_source id="Group">
|
||||
<name>Group</name>
|
||||
</business_source>
|
||||
</entity_business_source>
|
||||
36
install/langs/en/data/source.xml
Normal file
36
install/langs/en/data/source.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0"?>
|
||||
<entity_source>
|
||||
<source id="Direct_Website">
|
||||
<name>Direct Website</name>
|
||||
</source>
|
||||
<source id="Walk_in">
|
||||
<name>Walk-in</name>
|
||||
</source>
|
||||
<source id="Phone">
|
||||
<name>Phone</name>
|
||||
</source>
|
||||
<source id="Email">
|
||||
<name>Email</name>
|
||||
</source>
|
||||
<source id="Social_Media">
|
||||
<name>Social Media</name>
|
||||
</source>
|
||||
<source id="WhatsApp">
|
||||
<name>WhatsApp</name>
|
||||
</source>
|
||||
<source id="Booking_com">
|
||||
<name>Booking.com</name>
|
||||
</source>
|
||||
<source id="Expedia">
|
||||
<name>Expedia</name>
|
||||
</source>
|
||||
<source id="GoMMT">
|
||||
<name>GoMMT (GoIbibo/MakeMyTrip)</name>
|
||||
</source>
|
||||
<source id="Agoda">
|
||||
<name>Agoda</name>
|
||||
</source>
|
||||
<source id="Airbnb">
|
||||
<name>Airbnb</name>
|
||||
</source>
|
||||
</entity_source>
|
||||
@@ -37,6 +37,7 @@
|
||||
<tab id="Delivery_Slips" name="Delivery Slips"/>
|
||||
<tab id="Credit_Slips" name="Credit Slips"/>
|
||||
<tab id="Statuses" name="Statuses"/>
|
||||
<tab id="Sources" name="Business Sources"/>
|
||||
<tab id="Order_Messages" name="Order Messages"/>
|
||||
<tab id="Customers_1" name="Customers"/>
|
||||
<tab id="Addresses" name="Addresses"/>
|
||||
|
||||
@@ -537,6 +537,14 @@ class InstallModelInstall extends InstallAbstractModel
|
||||
Configuration::updateGlobalValue('PS_OS_OUTOFSTOCK_PAID', (int)Configuration::get('PS_OS_OUTOFSTOCK'));
|
||||
}
|
||||
|
||||
// Set the default Booking Source (Direct Website)
|
||||
$id_default_source = (int)Db::getInstance()->getValue(
|
||||
'SELECT `id_source` FROM '._DB_PREFIX_.'source WHERE `source_code` = \'DIRECT_WEBSITE\''
|
||||
);
|
||||
if ($id_default_source) {
|
||||
Configuration::updateGlobalValue('PS_DEFAULT_BOOKING_SOURCE', $id_default_source);
|
||||
}
|
||||
|
||||
// Set logo configuration
|
||||
if (file_exists(_PS_IMG_DIR_.'logo.png')) {
|
||||
list($width, $height) = getimagesize(_PS_IMG_DIR_.'logo.png');
|
||||
|
||||
44
js/admin/sources.js
Normal file
44
js/admin/sources.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License version 3.0
|
||||
* that is bundled with this package in the file LICENSE.md
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/license/osl-3-0-php
|
||||
*
|
||||
* @author Webkul IN
|
||||
* @copyright Since 2010 Webkul
|
||||
* @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0
|
||||
*/
|
||||
|
||||
$(document).on('click', '.merge-source-btn', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $btn = $(this);
|
||||
|
||||
$('.loading_overlay').show();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: $btn.data('ajax-url'),
|
||||
dataType: 'JSON',
|
||||
cache: false,
|
||||
data: {
|
||||
ajax: true,
|
||||
action: 'InitMergeSourceModal',
|
||||
id_source: $btn.data('id-source'),
|
||||
id_source_type: $btn.data('id-source-type')
|
||||
},
|
||||
success: function (result) {
|
||||
if (!result.hasError && result.modalHtml) {
|
||||
$('#merge_source_modal').remove();
|
||||
$('#footer').next('.bootstrap').append(result.modalHtml);
|
||||
$('#merge_source_modal').modal('show');
|
||||
} else {
|
||||
showErrorMessage(result.error || 'Could not open the merge form.');
|
||||
}
|
||||
},
|
||||
complete: function () {
|
||||
$('.loading_overlay').hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user