From 57f5fa24324149cfdf514af823167e9bcd7750ba Mon Sep 17 00:00:00 2001 From: "vishalsingh.qlo325" Date: Thu, 12 Jun 2025 17:33:10 +0530 Subject: [PATCH 01/10] Updated the flow for feature prices, added multiple date wise rules in a feature price for a room type --- .../template/controllers/products/prices.tpl | 2 +- classes/webservice/WebserviceRequest.php | 4 + .../WebserviceSpecificManagementBookings.php | 33 +- controllers/admin/AdminCartsController.php | 36 +- controllers/admin/AdminImportController.php | 41 +- controllers/admin/AdminOrdersController.php | 4 +- .../classes/HotelBookingDetail.php | 2 +- .../classes/HotelCartBookingData.php | 24 +- .../classes/HotelReservationSystemDb.php | 19 +- .../classes/HotelRoomTypeFeaturePricing.php | 475 ++++++++++++------ .../HotelRoomTypeFeaturePricingRule.php | 80 +++ .../admin/AdminHotelFeaturePricesSettings.php | 309 +++++++----- modules/hotelreservationsystem/define.php | 1 + .../hotelreservationsystem.php | 3 +- .../views/css/HotelReservationAdmin.css | 25 +- .../views/js/HotelReservationAdmin.js | 205 ++++++-- .../admin/_partials/feature_price_rules.tpl | 94 ++++ .../helpers/form/form.tpl | 155 ++---- modules/qlocleaner/qlocleaner.php | 3 + 19 files changed, 958 insertions(+), 557 deletions(-) create mode 100644 modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricingRule.php create mode 100644 modules/hotelreservationsystem/views/templates/admin/_partials/feature_price_rules.tpl diff --git a/admin/themes/default/template/controllers/products/prices.tpl b/admin/themes/default/template/controllers/products/prices.tpl index 32fe8a418..c27d0906c 100644 --- a/admin/themes/default/template/controllers/products/prices.tpl +++ b/admin/themes/default/template/controllers/products/prices.tpl @@ -390,7 +390,7 @@ $(document).ready(function () { {l s='create advanced price rules.'}
- +
diff --git a/classes/webservice/WebserviceRequest.php b/classes/webservice/WebserviceRequest.php index 5bf43b07d..ff62a66e5 100644 --- a/classes/webservice/WebserviceRequest.php +++ b/classes/webservice/WebserviceRequest.php @@ -1487,6 +1487,10 @@ class WebserviceRequestCore if (!$this->hasErrors()) { $object->webservice_validation = 1; + if (isset($attributes->associations)) { + $object->associations = $attributes->associations; + } + if ($i18n && ($retValidateFieldsLang = $object->validateFieldsLang(false, true)) !== true) { $this->setError(400, 'Validation error: "'.$retValidateFieldsLang.'"', 84); return false; diff --git a/classes/webservice/WebserviceSpecificManagementBookings.php b/classes/webservice/WebserviceSpecificManagementBookings.php index 0f7e99a67..060028c5e 100644 --- a/classes/webservice/WebserviceSpecificManagementBookings.php +++ b/classes/webservice/WebserviceSpecificManagementBookings.php @@ -2930,38 +2930,19 @@ class WebserviceSpecificManagementBookingsCore Extends ObjectModel implements We */ public function createFeaturePrice($params) { - $feature_price_name = array(); - foreach (Language::getIDs(true) as $idLang) { - $feature_price_name[$idLang] = 'Api-Booking-Price'; - } - $numDays = HotelHelper::getNumberOfDays($params['date_from'], $params['date_to']); if (!$numDays) { $numDays = 1; } - $objRoomTypeFeaturePricing = new HotelRoomTypeFeaturePricing(); - $objRoomTypeFeaturePricing->id_product = (int) $params['id_product']; - $objRoomTypeFeaturePricing->id_cart = (int) $params['id_cart']; - $objRoomTypeFeaturePricing->id_guest = (int) $params['id_guest']; - $objRoomTypeFeaturePricing->id_room = (int) $params['id_room']; - $objRoomTypeFeaturePricing->feature_price_name = $feature_price_name; - $objRoomTypeFeaturePricing->date_selection_type = HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE; - $objRoomTypeFeaturePricing->date_from = $params['date_from']; - $objRoomTypeFeaturePricing->date_to = $params['date_to']; - $objRoomTypeFeaturePricing->is_special_days_exists = 0; - $objRoomTypeFeaturePricing->special_days = json_encode(false); - $objRoomTypeFeaturePricing->impact_way = HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE; - $objRoomTypeFeaturePricing->impact_type = HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE; - $objRoomTypeFeaturePricing->impact_value = $params['price']/$numDays; - $objRoomTypeFeaturePricing->active = 1; - $objRoomTypeFeaturePricing->groupBox = array_column(Group::getGroups(Configuration::get('PS_LANG_DEFAULT')), 'id_group'); + $params['name'] = 'Api-Booking-Price'; + $params['date_selection_type'] = HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE; + $params['impact_type'] = HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE; + $params['price'] /= $numDays; + $params['is_special_days_exists'] = 0; + $params['special_days'] = json_encode(false); - if ($objRoomTypeFeaturePricing->add()) { - return $objRoomTypeFeaturePricing->id; - } - - return false; + return HotelRoomTypeFeaturePricing::createRoomTypeFeaturePrice($params); } /** diff --git a/controllers/admin/AdminCartsController.php b/controllers/admin/AdminCartsController.php index 173ceef08..e21a86886 100644 --- a/controllers/admin/AdminCartsController.php +++ b/controllers/admin/AdminCartsController.php @@ -978,28 +978,22 @@ class AdminCartsControllerCore extends AdminController if ($this->tabAccess['edit'] === 1) { HotelRoomTypeFeaturePricing::deleteFeaturePrices($id_cart, $id_product, $id_room, $date_from, $date_to); - $feature_price_name = array(); - foreach (Language::getIDs(true) as $id_lang) { - $feature_price_name[$id_lang] = 'Auto-generated'; - } + HotelRoomTypeFeaturePricing::createRoomTypeFeaturePrice( + array( + 'id_product' => $id_product, + 'id_cart' => $id_cart, + 'id_guest' => (int) $this->context->cookie->id_guest, + 'id_room' => $id_room, + 'date_selection_type' => HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE, + 'date_from' => $date_from, + 'date_to' => $date_to, + 'is_special_days_exists' => 0, + 'impact_way' => HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE, + 'impact_type' => HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE, + 'impact_value' => $price + ) + ); - $hrt_feature_price = new HotelRoomTypeFeaturePricing(); - $hrt_feature_price->id_product = $id_product; - $hrt_feature_price->id_cart = $id_cart; - $hrt_feature_price->id_guest = (int) $this->context->cookie->id_guest; - $hrt_feature_price->id_room = $id_room; - $hrt_feature_price->feature_price_name = $feature_price_name; - $hrt_feature_price->date_selection_type = HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE; - $hrt_feature_price->date_from = $date_from; - $hrt_feature_price->date_to = $date_to; - $hrt_feature_price->is_special_days_exists = 0; - $hrt_feature_price->special_days = json_encode(false); - $hrt_feature_price->impact_way = HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE; - $hrt_feature_price->impact_type = HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE; - $hrt_feature_price->impact_value = $price; - $hrt_feature_price->active = 1; - $hrt_feature_price->groupBox = array_column(Group::getGroups($this->context->language->id), 'id_group'); - $hrt_feature_price->add(); $objHotelCartBookingData = new HotelCartBookingData(); $bookingsInfo = $objHotelCartBookingData->getCartFormatedBookinInfoByIdCart($id_cart); diff --git a/controllers/admin/AdminImportController.php b/controllers/admin/AdminImportController.php index 11242fc56..af1604da5 100644 --- a/controllers/admin/AdminImportController.php +++ b/controllers/admin/AdminImportController.php @@ -2615,7 +2615,7 @@ class AdminImportControllerCore extends AdminController $this->context->cart->id_guest ); $objHotelCartBookingData = new HotelCartBookingData(); - if ($idRooms = $objHotelCartBookingData->getCustomerIdRoomsByIdCartIdProduct( + if ($bookingCartData = $objHotelCartBookingData->getCustomerIdRoomsByIdCartIdProduct( $this->context->cart->id, $orderProduct['id_product'], date('Y-m-d', strtotime($dateFrom)), @@ -2632,28 +2632,23 @@ class AdminImportControllerCore extends AdminController $taxRateM = $taxRate/100; if (isset($orderProduct['amount'])) { $orderProduct['amount'] = (float)$orderProduct['amount']/(1+$taxRateM); - foreach ($idRooms as $idRoom) { - $objRoomFeaturePrice = new HotelRoomTypeFeaturePricing(); - $objRoomFeaturePrice->id_product = (int) $orderProduct['id_product']; - $objRoomFeaturePrice->id_cart = (int) $this->context->cart->id; - $objRoomFeaturePrice->id_guest = (int) $this->context->cart->id_guest; - foreach(Language::getLanguages(true) as $lang) { - $objRoomFeaturePrice->feature_price_name[$lang['id_lang']] = 'csvprice'; - } - - $objRoomFeaturePrice->date_selection_type = HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE; - $objRoomFeaturePrice->date_from = date('Y-m-d', strtotime($dateFrom)); - $objRoomFeaturePrice->date_to = date('Y-m-d', strtotime($dateTo)); - $objRoomFeaturePrice->is_special_days_exists = 0; - $objRoomFeaturePrice->id_room = $idRoom['id_room']; - $objRoomFeaturePrice->special_days = json_encode(false); - $objRoomFeaturePrice->impact_way = HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE; - $objRoomFeaturePrice->impact_type = HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE; - $objRoomFeaturePrice->impact_value = $orderProduct['amount']; - $objRoomFeaturePrice->active = 1; - $objRoomFeaturePrice->groupBox = array_column(Group::getGroups($this->context->language->id), 'id_group'); - $objRoomFeaturePrice->add(); - $featurePrices[] = $objRoomFeaturePrice->id; + foreach ($bookingCartData as $bookingCart) { + $featurePrices[] = HotelRoomTypeFeaturePricing::createRoomTypeFeaturePrice( + array( + 'name' => 'csvprice', + 'id_product' => (int) $orderProduct['id_product'], + 'id_cart' => (int) $this->context->cart->id, + 'id_guest' => (int) $this->context->cart->id_guest, + 'date_selection_type' => HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE, + 'date_from' => date('Y-m-d', strtotime($dateFrom)), + 'date_to' => date('Y-m-d', strtotime($dateTo)), + 'is_special_days_exists' => 0, + 'id_room' => $bookingCart['id_room'], + 'impact_way' => HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE, + 'impact_type' => HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE, + 'impact_value' => $orderProduct['amount'], + ) + ); } } } diff --git a/controllers/admin/AdminOrdersController.php b/controllers/admin/AdminOrdersController.php index 028976d07..b3c3d573a 100644 --- a/controllers/admin/AdminOrdersController.php +++ b/controllers/admin/AdminOrdersController.php @@ -4824,7 +4824,7 @@ class AdminOrdersControllerCore extends AdminController if ($createFeaturePrice) { $featurePriceParams['id_room'] = $room_info['id_room']; $featurePriceParams = array_merge($featurePriceParams, array('date_from' => $date_from, 'date_to' => $date_to)); - HotelRoomTypeFeaturePricing::createAutoFeaturePrice($featurePriceParams); + HotelRoomTypeFeaturePricing::createRoomTypeFeaturePrice($featurePriceParams); } } else { break; @@ -5663,7 +5663,7 @@ class AdminOrdersControllerCore extends AdminController 'date_from' => $new_date_from, 'date_to' => $new_date_to ); - HotelRoomTypeFeaturePricing::createAutoFeaturePrice($params); + HotelRoomTypeFeaturePricing::createRoomTypeFeaturePrice($params); $roomTotalPrice = HotelRoomTypeFeaturePricing::getRoomTypeTotalPrice( $id_product, diff --git a/modules/hotelreservationsystem/classes/HotelBookingDetail.php b/modules/hotelreservationsystem/classes/HotelBookingDetail.php index d15b53785..efc389e0d 100644 --- a/modules/hotelreservationsystem/classes/HotelBookingDetail.php +++ b/modules/hotelreservationsystem/classes/HotelBookingDetail.php @@ -1998,7 +1998,7 @@ class HotelBookingDetail extends ObjectModel $featurePriceParams, array('date_from' => $objOldHotelBooking->date_from, 'date_to' => $objOldHotelBooking->date_to) ); - HotelRoomTypeFeaturePricing::createAutoFeaturePrice($featurePriceParams); + HotelRoomTypeFeaturePricing::createRoomTypeFeaturePrice($featurePriceParams); } } else { return false; diff --git a/modules/hotelreservationsystem/classes/HotelCartBookingData.php b/modules/hotelreservationsystem/classes/HotelCartBookingData.php index 8a7a1d2c0..44bc5712c 100644 --- a/modules/hotelreservationsystem/classes/HotelCartBookingData.php +++ b/modules/hotelreservationsystem/classes/HotelCartBookingData.php @@ -1443,7 +1443,7 @@ class HotelCartBookingData extends ObjectModel * @param [int] $id_group [id_group for which price is need (if available for the passed group)] * @return [array|false] [returns array containg info of the feature plan if foung otherwise returns false] */ - public function getProductFeaturePricePlanByDateByPriority( + public static function getProductFeaturePricePlanByDateByPriority( $id_product, $date, $id_group, @@ -1453,10 +1453,12 @@ class HotelCartBookingData extends ObjectModel ) { if ($id_cart && $id_room) { if ($featurePrice = Db::getInstance()->getRow('SELECT * FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` fp + LEFT JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_rule` fpr + ON (fpr.`id_feature_price` = fp.`id_feature_price`) WHERE fp.`id_product` = '.(int) $id_product.' AND fp.`id_cart` = '.(int) $id_cart.' AND fp.`id_guest` = '.(int) $id_guest.' AND fp.`id_room` = '.(int) $id_room.' - AND fp.`active` = 1 AND fp.`date_from` <= \''.pSQL($date).'\' - AND fp.`date_to` >= \''.pSQL($date).'\'') + AND fp.`active` = 1 AND fpr.`date_from` <= \''.pSQL($date).'\' + AND fpr.`date_to` >= \''.pSQL($date).'\'') ) { return $featurePrice; } @@ -1472,8 +1474,10 @@ class HotelCartBookingData extends ObjectModel 'SELECT * FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` fp'. (Group::isFeatureActive() ? ' INNER JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_group` fpg ON (fp.`id_feature_price` = fpg.`id_feature_price` AND fpg.`id_group` = '.(int) $id_group.')' : '').' + LEFT JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_rule` fpr + ON (fpr.`id_feature_price` = fp.`id_feature_price`) WHERE fp.`id_cart` = 0 AND fp.`id_product`='.(int) $id_product.' AND fp.`active`=1 - AND fp.`date_selection_type` = '.(int) HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC.' AND fp.`date_from` = \''.pSQL($date).'\'' + AND fpr.`date_selection_type` = '.(int) HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC.' AND fpr.`date_from` = \''.pSQL($date).'\'' )) { return $featurePrice; } @@ -1482,9 +1486,11 @@ class HotelCartBookingData extends ObjectModel 'SELECT * FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` fp'. (Group::isFeatureActive() ? ' INNER JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_group` fpg ON (fp.`id_feature_price` = fpg.`id_feature_price` AND fpg.`id_group` = '.(int) $id_group.')' : '').' + LEFT JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_rule` fpr + ON (fpr.`id_feature_price` = fp.`id_feature_price`) WHERE fp.`id_cart` = 0 AND fp.`id_product`='.(int) $id_product.' - AND fp.`is_special_days_exists`=1 AND fp.`active`=1 AND fp.`date_from` <= \''.pSQL($date).'\' - AND fp.`date_to` >= \''.pSQL($date).'\'' + AND fpr.`is_special_days_exists`=1 AND fp.`active`=1 AND fpr.`date_from` <= \''.pSQL($date).'\' + AND fpr.`date_to` >= \''.pSQL($date).'\'' )) { foreach ($featurePrice as $fRow) { $specialDays = json_decode($fRow['special_days']); @@ -1498,9 +1504,11 @@ class HotelCartBookingData extends ObjectModel 'SELECT * FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` fp'. (Group::isFeatureActive() ? ' INNER JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_group` fpg ON (fp.`id_feature_price` = fpg.`id_feature_price` AND fpg.`id_group` = '.(int) $id_group.')' : '').' - WHERE fp.`id_cart` = 0 AND fp.`id_product`='.(int) $id_product.' AND fp.`date_selection_type` = '.(int) HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE.' + LEFT JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_rule` fpr + ON (fpr.`id_feature_price` = fp.`id_feature_price`) + WHERE fp.`id_cart` = 0 AND fp.`id_product`='.(int) $id_product.' AND fpr.`date_selection_type` = '.(int) HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE.' AND `is_special_days_exists`=0 AND `active`=1 - AND fp.`date_from` <= \''.pSQL($date).'\' AND fp.`date_to` >= \''.pSQL($date).'\'' + AND fpr.`date_from` <= \''.pSQL($date).'\' AND fpr.`date_to` >= \''.pSQL($date).'\'' )) { return $featurePrice; } diff --git a/modules/hotelreservationsystem/classes/HotelReservationSystemDb.php b/modules/hotelreservationsystem/classes/HotelReservationSystemDb.php index 3552be415..5ae782bb0 100644 --- a/modules/hotelreservationsystem/classes/HotelReservationSystemDb.php +++ b/modules/hotelreservationsystem/classes/HotelReservationSystemDb.php @@ -284,11 +284,6 @@ class HotelReservationSystemDb `id_cart` int(11) NOT NULL DEFAULT '0', `id_guest` int(11) NOT NULL DEFAULT '0', `id_room` int(11) NOT NULL DEFAULT '0', - `date_from` date NOT NULL, - `date_to` date NOT NULL, - `is_special_days_exists` tinyint(1) NOT NULL, - `date_selection_type` tinyint(1) NOT NULL, - `special_days` text, `impact_way` tinyint(1) NOT NULL, `impact_type` tinyint(1) NOT NULL, `impact_value` decimal(20,6) NOT NULL DEFAULT '0.000000', @@ -298,6 +293,19 @@ class HotelReservationSystemDb PRIMARY KEY (`id_feature_price`) ) ENGINE="._MYSQL_ENGINE_." DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;", + "CREATE TABLE IF NOT EXISTS `"._DB_PREFIX_."htl_room_type_feature_pricing_rule` ( + `id_feature_price_rule` int(11) NOT NULL AUTO_INCREMENT, + `id_feature_price` int(11) NOT NULL, + `is_special_days_exists` tinyint(1) NOT NULL, + `date_selection_type` tinyint(1) NOT NULL, + `special_days` text, + `date_from` date NOT NULL, + `date_to` date NOT NULL, + `date_add` datetime NOT NULL, + `date_upd` datetime NOT NULL, + PRIMARY KEY (`id_feature_price_rule`) + ) ENGINE="._MYSQL_ENGINE_." DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;", + "CREATE TABLE IF NOT EXISTS `"._DB_PREFIX_."htl_room_type_feature_pricing_lang` ( `id_feature_price` int(10) unsigned NOT NULL, `id_lang` int(10) unsigned NOT NULL, @@ -582,6 +590,7 @@ class HotelReservationSystemDb `'._DB_PREFIX_.'htl_room_type_feature_pricing`, `'._DB_PREFIX_.'htl_room_type_feature_pricing_lang`, `'._DB_PREFIX_.'htl_room_type_feature_pricing_group`, + `'._DB_PREFIX_.'htl_room_type_feature_pricing_rule`, `'._DB_PREFIX_.'htl_room_type_global_demand`, `'._DB_PREFIX_.'htl_room_type_global_demand_lang`, `'._DB_PREFIX_.'htl_room_type_global_demand_advance_option`, diff --git a/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricing.php b/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricing.php index e20ccf9e0..5975dbc85 100644 --- a/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricing.php +++ b/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricing.php @@ -25,11 +25,6 @@ class HotelRoomTypeFeaturePricing extends ObjectModel public $id_guest = 0; public $id_room = 0; public $feature_price_name; - public $date_selection_type; - public $date_from; - public $date_to; - public $is_special_days_exists; - public $special_days; public $impact_way; public $impact_type; public $impact_value; @@ -60,12 +55,7 @@ class HotelRoomTypeFeaturePricing extends ObjectModel 'id_cart' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'id_guest' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'id_room' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'date_from' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), - 'date_to' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), 'impact_way' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'is_special_days_exists' => array('type' => self::TYPE_INT, 'required' => true), - 'date_selection_type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), - 'special_days' => array('type' => self::TYPE_STRING, 'validate' => 'isString'), 'impact_type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), 'impact_value' => array('type' => self::TYPE_FLOAT, 'required' => true), 'active' => array('type' => self::TYPE_INT), @@ -93,6 +83,19 @@ class HotelRoomTypeFeaturePricing extends ObjectModel ), 'associations' => array( 'groups' => array('resource' => 'group'), + 'price_rules' => array( + 'resource' => 'price_rule', + 'getter' => 'getWsAdvancePriceRule', + 'setter' => 'setWsAdvancePriceRule', + 'fields' => array( + 'id' => array(), + 'date_from' => array(), + 'date_to' => array(), + 'date_selection_type' => array(), + 'is_special_days_exists' => array(), + 'special_days' => array(), + ), + ), ) ); @@ -123,119 +126,109 @@ class HotelRoomTypeFeaturePricing extends ObjectModel { // first call to delete all the group entries $this->cleanGroups(); + $objFeaturePriceRule = new HotelRoomTypeFeaturePricingRule(); + if ($oldFeaturePriceRules = $objFeaturePriceRule->getRulesByIdFeaturePrice($this->id)) { + $objFeaturePriceRule->deleteFeaturePriceRules($oldFeaturePriceRules); + } + return parent::delete(); } - public function getFeaturePriceInfo($idFeaturePrice) - { - if (!$idFeaturePrice) { - return false; - } - return Db::getInstance()->getRow( - 'SELECT * FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` WHERE `id_feature_price`='. - (int) $idFeaturePrice - ); - } - - /** - * [getRoomTypeActiveFeaturePrices returns room type active feature price plans] - * @param [int] $id_product [id of the product] - * @return [array|false] [returns array of all active feature plans of the room type if found else returns false] - */ - public static function getRoomTypeActiveFeaturePrices($id_product) - { - return Db::getInstance()->executeS( - 'SELECT * FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` - WHERE `id_product`='.(int) $id_product.' AND `active`=1' - ); - } - - /** - * [getRoomTypeActiveFeaturePricesByDateRange returns room type active feature price plans by supplied date Range] - * @param [int] $id_product [id of the product] - * @param [date] $date_from [start date of the date range] - * @param [date] $date_to [end date of the date range] - * @return [array|false] [returns array of all active feature plans of the room type if found else returns false] - */ - public static function getRoomTypeActiveFeaturePricesByDateRange($id_product, $date_from, $date_to) - { - return Db::getInstance()->executeS( - 'SELECT * FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` - WHERE (`id_product`=0 OR `id_product`='.(int) $id_product.') - AND `active`=1 AND `date_from` <= \''.$date_to.'\' AND `date_to` >= \''.$date_from.'\'' - ); - } - - /** - * [checkRoomTypeFeaturePriceExistance returns room type active feature price plan by supplied date Range and supplied feature price plan type else returns false] - * @param [int] $id_product [id of the product] - * @param [date] $date_from [start date of the date range] - * @param [date] $date_to [end date of the date range] - * @param [type] $type [Type of the feature price plan must be among 'specific_date', 'special_day' and 'date_range'] - * @return [array|false] [returns room type active feature price plan by supplied date Range and supplied feature price plan type else returns false] - */ - public function checkRoomTypeFeaturePriceExistance( - $id_product, - $date_from, - $date_to, + public function getExistingFeaturePriceRules( + $idRoomType, $groups, - $type = 'date_range', - $current_Special_days = false, - $id_feature_price = 0 + $idFeaturePrice, + $featurePriceRules ) { - $date_from = date('Y-m-d', strtotime($date_from)); - $date_to = date('Y-m-d', strtotime($date_to)); - if ($type == 'specific_date') { - return Db::getInstance()->getRow( - 'SELECT * FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` rtfp - INNER JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_group` rtfpg - ON (rtfp.`id_feature_price` = rtfpg.`id_feature_price`) - WHERE rtfp.`id_product`='.(int) $id_product.' AND rtfp.`active`=1 - AND rtfp.`date_selection_type` = '.(int) self::DATE_SELECTION_TYPE_SPECIFIC.' - AND rtfp.`date_from` = \''.pSQL($date_from).'\' - AND rtfp.`id_feature_price`!='.(int) $id_feature_price.' - AND rtfpg.`id_group` IN ('.pSQL(implode(', ',$groups)).')' - ); - } elseif ($type == 'special_day') { - $featurePrices = Db::getInstance()->executeS( - 'SELECT * FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` rtfp - INNER JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_group` rtfpg - ON (rtfp.`id_feature_price` = rtfpg.`id_feature_price`) - WHERE rtfp.`id_product`='.(int) $id_product.' - AND rtfp.`is_special_days_exists`=1 AND `active`=1 - AND rtfp.`date_from` < \''.pSQL($date_to).'\' - AND rtfp.`date_to` > \''.pSQL($date_from).'\' - AND rtfp.`id_feature_price`!='.(int) $id_feature_price.' - AND rtfpg.`id_group` IN ('.pSQL(implode(', ',$groups)).')' - ); - if ($featurePrices) { - foreach ($featurePrices as $featurePrice) { - $specialDays = json_decode($featurePrice['special_days']); - $currentSpecialDays = json_decode($current_Special_days); - $commonValues = array_intersect($specialDays, $currentSpecialDays); - if ($commonValues) { - return $featurePrice; - } + $sql = 'SELECT *, GROUP_CONCAT(rtfpg.`id_group`) AS id_group FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing_rule` rtfpr + LEFT JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing` rtfp + ON (rtfpr.`id_feature_price` = rtfp.`id_feature_price` AND rtfp.`id_product`='.(int) $idRoomType.') + LEFT JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_group` rtfpg + ON (rtfp.`id_feature_price` = rtfpg.`id_feature_price` AND rtfpg.`id_group` IN ('.pSQL(implode(', ',$groups)).')) + WHERE rtfpr.`id_feature_price`!='.(int) $idFeaturePrice.' AND rtfp.`active`= 1'; + $sqlWhere = ''; + foreach ($featurePriceRules as $featurePriceRule) { + if ($sqlWhere != '') { + $sqlWhere .= ' OR '; + } + + $dateFrom = date('Y-m-d', strtotime($featurePriceRule['date_from'])); + $dateTo = date('Y-m-d', strtotime($featurePriceRule['date_to'])); + if ($featurePriceRule['date_selection_type'] == self::DATE_SELECTION_TYPE_SPECIFIC) { + $sqlWhere .= ' (rtfpr.`date_selection_type` = '.(int) self::DATE_SELECTION_TYPE_SPECIFIC.' + AND rtfpr.`date_from` = \''.pSQL($dateFrom).'\')'; + } else if ($featurePriceRule['date_selection_type'] == self::DATE_SELECTION_TYPE_RANGE) { + if ($featurePriceRule['is_special_days_exists']) { + $sqlWhere .= ' (rtfpr.`is_special_days_exists`=1 + AND rtfpr.`date_from` < \''.pSQL($dateTo).'\' + AND rtfpr.`date_to` > \''.pSQL($dateFrom).'\')'; + } else { + $sqlWhere .= ' (rtfpr.`date_selection_type` = '.(int) self::DATE_SELECTION_TYPE_RANGE.' + AND rtfpr.`is_special_days_exists`=0 + AND rtfpr.`date_from` <= \''.pSQL($dateTo).'\' + AND rtfpr.`date_to` >= \''.pSQL($dateFrom).'\')'; } } - return false; - } elseif ($type == 'date_range') { - return Db::getInstance()->getRow( - 'SELECT * FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` rtfp - INNER JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_group` rtfpg - ON (rtfp.`id_feature_price` = rtfpg.`id_feature_price`) - WHERE rtfp.`id_product`='.(int) $id_product.' AND rtfp.`active`=1 - AND rtfp.`date_selection_type` = '.(int) self::DATE_SELECTION_TYPE_RANGE.' - AND rtfp.`is_special_days_exists`=0 - AND rtfp.`date_from` <= \''.pSQL($date_to).'\' - AND rtfp.`date_to` >= \''.pSQL($date_from).'\' - AND rtfp.`id_feature_price`!='.(int) $id_feature_price.' - AND rtfpg.`id_group` IN ('.pSQL(implode(', ',$groups)).')' - ); } - return false; + + if ($sqlWhere != '') { + $sqlWhere = ' AND ('.$sqlWhere.')'; + } + + $sql .= $sqlWhere.' GROUP BY rtfpr.`id_feature_price`'; + + return Db::getInstance()->executeS($sql); } + public function saveUpdateFeaturePrices($idFeaturePrice, $featurePriceRules) + { + $res = true; + $objFeaturePriceRule = new HotelRoomTypeFeaturePricingRule(); + if ($oldFeaturePriceRules = $objFeaturePriceRule->getRulesByIdFeaturePrice($idFeaturePrice)) { + $oldFeaturePriceRules = array_column($oldFeaturePriceRules, 'id_feature_price_rule', 'id_feature_price_rule'); + } + + if ($featurePriceRules) { + foreach ($featurePriceRules as $featurePriceRule) { + if (isset($featurePriceRule['id']) && in_array($featurePriceRule['id'], $oldFeaturePriceRules)) { + $objFeaturePriceRule = new HotelRoomTypeFeaturePricingRule($featurePriceRule['id']); + unset($oldFeaturePriceRules[$featurePriceRule['id']]); + } else { + $objFeaturePriceRule = new HotelRoomTypeFeaturePricingRule(); + } + + $objFeaturePriceRule->id_feature_price = $idFeaturePrice; + $objFeaturePriceRule->date_from = $featurePriceRule['date_from']; + $objFeaturePriceRule->date_to = $featurePriceRule['date_to']; + $objFeaturePriceRule->date_selection_type = isset($featurePriceRule['date_selection_type']) ? $featurePriceRule['date_selection_type'] : HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE; + $objFeaturePriceRule->special_days = json_encode(array()); + if ($objFeaturePriceRule->date_selection_type == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE + && $featurePriceRule['is_special_days_exists'] + ) { + $objFeaturePriceRule->is_special_days_exists = isset($featurePriceRule['is_special_days_exists']) ? $featurePriceRule['is_special_days_exists'] : 0; + if (isset($featurePriceRule['is_special_days_exists']) + && $featurePriceRule['is_special_days_exists'] + && isset($featurePriceRule['special_days']) + && $featurePriceRule['special_days'] + ) { + $objFeaturePriceRule->special_days = json_encode($featurePriceRule['special_days']); + } + } else { + $objFeaturePriceRule->is_special_days_exists = 0; + } + + $res &= $objFeaturePriceRule->save(); + } + } + + if ($oldFeaturePriceRules) { + $res &= $objFeaturePriceRule->deleteFeaturePriceRules($oldFeaturePriceRules); + } + + return $res; + } + + /** * [countFeaturePriceSpecialDays returns number of special days between a date range] * @param [array] $specialDays [array containing special days to be counted] @@ -309,9 +302,8 @@ class HotelRoomTypeFeaturePricing extends ObjectModel $context = Context::getContext(); $id_currency = Validate::isLoadedObject($context->currency) ? (int)$context->currency->id : (int)Configuration::get('PS_CURRENCY_DEFAULT'); - $hotelCartBookingData = new HotelCartBookingData(); for($currentDate = date('Y-m-d', strtotime($date_from)); $currentDate < date('Y-m-d', strtotime($date_to)); $currentDate = date('Y-m-d', strtotime('+1 day', strtotime($currentDate)))) { - if ($use_reduc && ($featurePrice = $hotelCartBookingData->getProductFeaturePricePlanByDateByPriority( + if ($use_reduc && ($featurePrice = HotelCartBookingData::getProductFeaturePricePlanByDateByPriority( $id_product, $currentDate, $id_group, @@ -492,9 +484,12 @@ class HotelRoomTypeFeaturePricing extends ObjectModel { $idLang = Context::getContext()->language->id; return Db::getInstance()->executeS( - 'SELECT hrfp.*, hrfpl.`feature_price_name` FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` hrfp + 'SELECT hrfp.*, hrfpr.`date_from`, hrfpr.`date_to`, hrfpr.`date_selection_type`, hrfpr.`is_special_days_exists`, hrfpr.`special_days`, hrfpl.`feature_price_name` + FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` hrfp LEFT JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_lang` hrfpl ON(hrfp.`id_feature_price` = hrfpl.`id_feature_price` AND hrfpl.`id_lang` = '.(int)$idLang.') + LEFT JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_rule` hrfpr + ON (hrfpr.`id_feature_price` = hrfp.`id_feature_price`) WHERE `id_product` = '.(int)$id_product.' AND `id_cart` = '.(int)$id_cart.' AND `id_guest` = '.(int)$id_guest.' AND `id_room` = '.(int)$id_room ); } @@ -545,13 +540,15 @@ class HotelRoomTypeFeaturePricing extends ObjectModel } $idfeaturePrices = Db::getInstance()->executeS( - 'SELECT `id_feature_price` FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` + 'SELECT hrfp.`id_feature_price` FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing` hrfp + LEFT JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_rule` hrfpr + ON (hrfpr.`id_feature_price` = hrfp.`id_feature_price`) WHERE 1'. - ($id_cart ? ' AND `id_cart` = '.(int) $id_cart : ''). - ($id_product ? ' AND `id_product` = '.(int) $id_product : ''). - ($id_room ? ' AND `id_room` = '.(int) $id_room : ''). - ($date_from ? ' AND `date_from` = "'.pSQL($date_from) .'"' : ''). - ($date_to ? ' AND `date_to` = "'.pSQL($date_to) .'"' : '') + ($id_cart ? ' AND hrfp.`id_cart` = '.(int) $id_cart : ''). + ($id_product ? ' AND hrfp.`id_product` = '.(int) $id_product : ''). + ($id_room ? ' AND hrfp.`id_room` = '.(int) $id_room : ''). + ($date_from ? ' AND hrfpr.`date_from` = "'.pSQL($date_from) .'"' : ''). + ($date_to ? ' AND hrfpr.`date_to` = "'.pSQL($date_to) .'"' : '') ); $res = true; foreach ($idfeaturePrices as $featurePrice) { @@ -640,25 +637,192 @@ class HotelRoomTypeFeaturePricing extends ObjectModel return true; } + public function getWsAdvancePriceRule() + { + return Db::getInstance()->executeS( + 'SELECT *, id_feature_price_rule AS `id` FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing_rule` + WHERE `id_feature_price` ='.(int)$this->id.' ORDER BY `id_feature_price` ASC' + ); + + } + + public function setWsAdvancePriceRule($priceRules) + { + foreach ($priceRules as $ruleKey => $priceRule) { + if ($priceRule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE + && $priceRule['is_special_days_exists'] + ) { + $specialDays = json_decode($priceRule['special_days'], true); + $priceRules[$ruleKey]['special_days'] = $specialDays; + } + } + + return $this->saveUpdateFeaturePrices($this->id, $priceRules); + } + + public function validateExistingFeaturePrice( + $roomTypeId, + $group, + $idFeaturePrice, + $featurePriceRules + ) { + $duplicateRules = array(); + if ($oldPriceRules = $this->getExistingFeaturePriceRules( + $roomTypeId, + $group, + $idFeaturePrice, + $featurePriceRules + )) { + foreach ($oldPriceRules as $oldPriceRule) { + foreach ($featurePriceRules as $ruleKey => $rule) { + if ($rule['date_selection_type'] == $oldPriceRule['date_selection_type']) { + if ($rule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { + if (strtotime($rule['date_from']) != strtotime($oldPriceRule['date_from'])) { + continue; + } else { + $duplicateRules[] = $ruleKey; + } + } else if ($rule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { + if (((strtotime($oldPriceRule['date_from']) < strtotime($rule['date_from'])) && (strtotime($oldPriceRule['date_to']) <= strtotime($rule['date_from']))) || ((strtotime($oldPriceRule['date_from']) > strtotime($rule['date_from'])) && (strtotime($oldPriceRule['date_from']) >= strtotime($rule['date_to'])))) { + continue; + } else { + if ($oldPriceRule['is_special_days_exists'] && $rule['is_special_days_exists']) { + if (!empty($oldPriceRule['special_days']) && !empty($rule['special_days'])) { + $existingDays = json_decode($oldPriceRule['special_days'], true); + if (array_intersect($existingDays, $rule['special_days'])) { + $duplicateRules[] = $ruleKey; + } + } + } else { + $duplicateRules[] = $ruleKey; + } + } + } + } + } + } + } + + return $duplicateRules; + } + public function validateFields($die = true, $error_return = false) { if (isset($this->webservice_validation) && $this->webservice_validation) { - $weekDays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']; - if($this->is_special_days_exists) { - if ($this->special_days - && ($specialDays = json_decode($this->special_days, true)) - ) { - if (is_array($specialDays) && $specialDays) { - if (count(array_diff($specialDays, $weekDays))) { - $message = Tools::displayError('Invalid special days. format must match with : ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]', false); + $priceRules = array(); + $idGroups = array(); + if (isset($this->associations)) { + foreach ($this->associations->children() as $association) { + if ($association->getName() == 'price_rules') { + $assocItems = $association->children(); + foreach ($assocItems as $assocItem) { + /** @var SimpleXMLElement $assocItem */ + $fields = $assocItem->children(); + $entry = array(); + foreach ($fields as $fieldName => $fieldValue) { + $entry[$fieldName] = (string)$fieldValue; + } + + $priceRules[] = $entry; + } + } else if ($association->getName() == 'groups') { + $assocItems = $association->children(); + foreach ($assocItems as $assocItem) { + /** @var SimpleXMLElement $assocItem */ + $fields = $assocItem->children(); + $entry = array(); + foreach ($fields as $fieldName => $fieldValue) { + $entry[$fieldName] = (string)$fieldValue; + } + + $idGroups[] = $entry; } - } else { - $message = Tools::displayError('Invalid special days. format must match with : ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]', false); } - } else { - $message = Tools::displayError('Invalid special days. format must match with : ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]', false); } } + if ($idGroups) { + $idGroups = array_column($idGroups, 'id'); + } + + if ($priceRules) { + $hasError = false; + $weekDays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']; + // check for invalid special days + foreach ($priceRules as $ruleKey => $priceRule) { + if ($priceRule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { + if ($priceRule['is_special_days_exists']) { + $specialDays = json_decode($priceRule['special_days'], true); + $priceRules[$ruleKey]['special_days'] = $specialDays; + if (is_array($specialDays) && $specialDays) { + if (count(array_diff($specialDays, $weekDays))) { + $message = Tools::displayError('Invalid special days. format must match with : ["mon", "tue", "wed", "thu", "fri", "sat", "sun"].', true); + $hasError = true; + break; + } + } else { + $message = Tools::displayError('Invalid special days. format must match with : ["mon", "tue", "wed", "thu", "fri", "sat", "sun"].', true); + $hasError = true; + break; + } + } + } + } + + if (!$hasError) { + // check for conflicting dates in the rules. + foreach ($priceRules as $priceRuleKey => $priceRule) { + foreach ($priceRules as $ruleKey => $rule) { + if ($priceRuleKey != $ruleKey) { + if ($rule['date_selection_type'] == $priceRule['date_selection_type']) { + if ($rule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { + if (strtotime($rule['date_from']) != strtotime($priceRule['date_from'])) { + continue; + } else { + $message = Tools::displayError('You can not add conflicting dates.', true); + $hasError = true; + break; + } + } else if ($rule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { + if (((strtotime($priceRule['date_from']) < strtotime($rule['date_from'])) && (strtotime($priceRule['date_to']) <= strtotime($rule['date_from']))) || ((strtotime($priceRule['date_from']) > strtotime($rule['date_from'])) && (strtotime($priceRule['date_from']) >= strtotime($rule['date_to'])))) { + continue; + } else { + if ($priceRule['is_special_days_exists'] && $rule['is_special_days_exists']) { + if (!empty($priceRule['special_days']) && !empty($rule['special_days'])) { + if (array_intersect($priceRule['special_days'], $rule['special_days'])) { + $message = Tools::displayError('You can not add conflicting days for similar date ranges.', true); + $hasError = true; + break; + } + } + } else { + $message = Tools::displayError('You can not add conflicting date ranges.', true); + $hasError = true; + break; + } + } + } + } + } + + } + } + } + + if (!$hasError) { + $hasDuplicate = $this->validateExistingFeaturePrice( + $this->id_product, + $idGroups, + $this->id, + $priceRules + ); + + if ($hasDuplicate) { + $message = Tools::displayError('An advanced price rule already exists with overlapping conditions.', false); + } + } + } else { + $message = Tools::displayError('Price rules are required.', false); + } if (isset($message) && $message != '') { if ($die) { @@ -671,30 +835,39 @@ class HotelRoomTypeFeaturePricing extends ObjectModel return parent::validateFields($die, $error_return); } - public static function createAutoFeaturePrice($params) + + public static function createRoomTypeFeaturePrice($params) { $context = Context::getContext(); $featurePriceName = array(); foreach (Language::getIDs(true) as $idLang) { - $featurePriceName[$idLang] = 'Auto-generated'; + if (isset($params['name']) && $params['name']) { + $featurePriceName[$idLang] = $params['name']; + } else { + $featurePriceName[$idLang] = 'Auto-generated'; + } + } + + if (isset($params['id']) && $params['id']) { + $objFeaturePricing = new HotelRoomTypeFeaturePricing($params['id']); + } else { + $objFeaturePricing = new HotelRoomTypeFeaturePricing(); } - $objFeaturePricing = new HotelRoomTypeFeaturePricing(); $objFeaturePricing->id_product = (int) $params['id_product']; - $objFeaturePricing->id_cart = (int) $params['id_cart']; - $objFeaturePricing->id_guest = (int) $params['id_guest']; - $objFeaturePricing->id_room = (int) $params['id_room']; + $objFeaturePricing->id_cart = (int) isset($params['id_cart']) ? $params['id_cart'] : 0; + $objFeaturePricing->id_guest = (int) isset($params['id_guest']) ? $params['id_guest'] : 0; + $objFeaturePricing->id_room = (int) isset($params['id_room']) ? $params['id_room'] : 0; $objFeaturePricing->feature_price_name = $featurePriceName; - $objFeaturePricing->date_selection_type = HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE; - $objFeaturePricing->date_from = date('Y-m-d', strtotime($params['date_from'])); - $objFeaturePricing->date_to = date('Y-m-d', strtotime($params['date_to'])); - $objFeaturePricing->is_special_days_exists = 0; - $objFeaturePricing->special_days = json_encode(false); - $objFeaturePricing->impact_way = HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE; - $objFeaturePricing->impact_type = HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE; - $objFeaturePricing->impact_value = $params['price']; - $objFeaturePricing->active = 1; - $objFeaturePricing->groupBox = array_column(Group::getGroups($context->language->id), 'id_group'); - $objFeaturePricing->add(); + $objFeaturePricing->impact_way = isset($params['impact_way']) ? $params['impact_way'] : HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE; + $objFeaturePricing->impact_type = isset($params['impact_type']) ? $params['impact_type'] : HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE; + $objFeaturePricing->impact_value = isset($params['price']) ? $params['price'] : 0; + $objFeaturePricing->active = isset($params['active']) ? $params['active'] : 1; + $objFeaturePricing->groupBox = !empty($params['groupBox']) ? $params['groupBox'] : array_column(Group::getGroups($context->language->id), 'id_group'); + if ($objFeaturePricing->add()) { + $objFeaturePricing->saveUpdateFeaturePrices($objFeaturePricing->id, $params['price_rules']); + } + + return $objFeaturePricing->id; } } diff --git a/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricingRule.php b/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricingRule.php new file mode 100644 index 000000000..769708ad7 --- /dev/null +++ b/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricingRule.php @@ -0,0 +1,80 @@ + +* @copyright 2010-2020 Webkul IN +* @license https://store.webkul.com/license.html +*/ + +class HotelRoomTypeFeaturePricingRule extends ObjectModel +{ + public $id_feature_price; + public $date_selection_type; + public $date_from; + public $date_to; + public $is_special_days_exists; + public $special_days; + public $date_add; + public $date_upd; + public static $definition = array( + 'table' => 'htl_room_type_feature_pricing_rule', + 'primary' => 'id_feature_price_rule', + 'multilang' => false, + 'fields' => array( + 'id_feature_price' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'date_from' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + 'date_to' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'is_special_days_exists' => array('type' => self::TYPE_INT, 'required' => true), + 'date_selection_type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'special_days' => array('type' => self::TYPE_STRING, 'validate' => 'isString'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), + 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate') + ) + ); + + protected $webserviceParameters = array( + 'objectsNodeName' => 'price_rules', + 'objectNodeName' => 'price_rule', + 'fields' => array( + 'id_feature_price' => array( + 'xlink_resource' => array( + 'resourceName' => 'feature_prices', + ) + ), + ) + ); + + public function getRulesByIdFeaturePrice($idFeaturePrice) + { + $sql = 'SELECT *, id_feature_price_rule AS `id` FROM `'._DB_PREFIX_.$this->table.'` + WHERE `id_feature_price` ='.(int) $idFeaturePrice; + + return Db::getInstance()->executeS($sql); + } + + public function deleteFeaturePriceRules($featurePriceRules) + { + $res = true; + if ($featurePriceRules) { + foreach ($featurePriceRules as $idFeaturePriceRules) { + $objFeaturePriceRule = new HotelRoomTypeFeaturePricingRule($idFeaturePriceRules); + $res &= $objFeaturePriceRule->delete(); + } + } + + return $res; + } + +} diff --git a/modules/hotelreservationsystem/controllers/admin/AdminHotelFeaturePricesSettings.php b/modules/hotelreservationsystem/controllers/admin/AdminHotelFeaturePricesSettings.php index 0635c619c..02d335244 100644 --- a/modules/hotelreservationsystem/controllers/admin/AdminHotelFeaturePricesSettings.php +++ b/modules/hotelreservationsystem/controllers/admin/AdminHotelFeaturePricesSettings.php @@ -36,6 +36,7 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController } parent::__construct(); + $this->_new_list_header_design = true; $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (pl.`id_product` = a.`id_product` AND pl.`id_lang`='.(int) $this->context->language->id.')'; $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'htl_room_type_feature_pricing_lang` fpl ON (a.id_feature_price = fpl.id_feature_price AND fpl.`id_lang` = '.(int) $this->context->language->id.')'; @@ -57,8 +58,16 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController $this->_where = ' AND a.`id_cart` = 0 AND a.`id_guest` = 0 AND a.`id_room` = 0'; - $impactWays = array(1 => $this->l('Decrease'), 2 => $this->l('Increase'), 3 => $this->l('Fix')); - $impactTypes = array(1 => $this->l('Percentage'), 2 => $this->l('Fixed Price')); + $impactWays = array( + HotelRoomTypeFeaturePricing::IMPACT_WAY_DECREASE => $this->l('Decrease'), + HotelRoomTypeFeaturePricing::IMPACT_WAY_INCREASE => $this->l('Increase'), + HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE => $this->l('Fix') + ); + + $impactTypes = array( + HotelRoomTypeFeaturePricing::IMPACT_TYPE_PERCENTAGE => $this->l('Percentage'), + HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE => $this->l('Fixed Price') + ); $priorities = Configuration::get('HTL_FEATURE_PRICING_PRIORITY'); $this->context->smarty->assign('featurePricePriority', explode(';', $priorities)); @@ -111,17 +120,6 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController 'callback' => 'setGroupAccessLabel', 'search' => false, ), - 'date_from' => array( - 'title' => $this->l('Date From'), - 'align' => 'center', - 'type' => 'date', - ), - 'date_to' => array( - 'title' => $this->l('Date To'), - 'align' => 'center', - 'type' => 'date', - 'callback' => 'getDateToValue', - ), 'active' => array( 'align' => 'center', 'title' => $this->l('Status'), @@ -176,20 +174,15 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController public function processStatus() { $objFeaturePricing = $this->loadObject(); + $objFeaturePriceRule = new HotelRoomTypeFeaturePricingRule(); if (!$objFeaturePricing->active) { - if ($this->validateExistingFeaturePrice( - $objFeaturePricing->date_selection_type, + if ($this->object->validateExistingFeaturePrice( $objFeaturePricing->id_product, - $objFeaturePricing->date_from, - $objFeaturePricing->date_to, $objFeaturePricing->getGroups($objFeaturePricing->id), $objFeaturePricing->id, - $objFeaturePricing->is_special_days_exists, - $objFeaturePricing->special_days - - + $objFeaturePriceRule->getRulesByIdFeaturePrice($objFeaturePricing->id) )) { - $this->errors[] = $this->l('An advanced price rule already exists in which some dates are common with this plan. Please select a different date range.'); + $this->errors[] = $this->l('An advanced price rule already exists with overlapping conditions. Please update the existing rule to activate this one.'); return ; } } @@ -221,17 +214,21 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController public function renderForm() { + if (!$this->loadObject(true)) { + return false; + } + $smartyVars = array(); $objCurrency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); $currencySign = $objCurrency->sign; - $dateFrom = date('d-m-Y'); - $dateTo = date('d-m-Y', strtotime($dateFrom) + 86400); + $dateFrom = date('Y-m-d'); + $dateTo = date('Y-m-d', strtotime($dateFrom) + 86400); $currentLangId = $this->default_form_language ? $this->default_form_language : Configuration::get('PS_LANG_DEFAULT'); $smartyVars['languages'] = Language::getLanguages(false); $smartyVars['currentLang'] = Language::getLanguage((int) $currentLangId); - if ($this->display == 'edit') { + if ($this->display == 'edit' && $this->object->id) { $idFeaturePrice = Tools::getValue('id_feature_price'); if (Validate::isLoadedObject( $objFeaturePrice = new HotelRoomTypeFeaturePricing($idFeaturePrice) @@ -241,12 +238,24 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController $smartyVars['productName'] = $product->name; } } - if ($objFeaturePrice->special_days) { - $smartyVars['special_days'] = (array)json_decode($objFeaturePrice->special_days); - } + $smartyVars['objFeaturePrice'] = $objFeaturePrice; $smartyVars['edit'] = 1; + $objFeaturePriceRule = new HotelRoomTypeFeaturePricingRule(); + if ($advancePriceRules = $objFeaturePriceRule->getRulesByIdFeaturePrice($objFeaturePrice->id)) { + foreach ($advancePriceRules as $priceRuleKey => $advancePriceRule) { + if ($advancePriceRule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { + $advancePriceRules[$priceRuleKey]['specific_date'] = $advancePriceRule['date_from']; + unset($advancePriceRules[$priceRuleKey]['date_from']); + unset($advancePriceRules[$priceRuleKey]['date_to']); + } else if ($advancePriceRule['is_special_days_exists']) { + $advancePriceRules[$priceRuleKey]['special_days'] = json_decode($advancePriceRule['special_days'], true); + } + } + } + + $smartyVars['advancePriceRules'] = $advancePriceRules; $smartyVars['feature_price_groups'] = $objFeaturePrice->getGroups($idFeaturePrice); } else { $tree = new HelperTree('hotels-tree'); @@ -272,6 +281,7 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController $smartyVars['hotel_tree'] = $tree->render(); } + $smartyVars['week_days'] = $this->getWeekDays(); $smartyVars['defaultcurrency_sign'] = $currencySign; $smartyVars['date_from'] = $dateFrom; $smartyVars['date_to'] = $dateTo; @@ -287,6 +297,19 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController return parent::renderForm(); } + public function getWeekDays() + { + return array( + 'mon' => $this->l('Mon'), + 'tue' => $this->l('Tue'), + 'wed' => $this->l('Wed'), + 'thu' => $this->l('Thu'), + 'fri' => $this->l('Fri'), + 'sat' => $this->l('Sat'), + 'sun' => $this->l('Sun') + ); + } + public function postProcess() { if (Tools::isSubmit('submitAddFeaturePricePriority')) { @@ -307,72 +330,26 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController } } - public function validateExistingFeaturePrice( - $dateSelectionType, - $roomTypeId, - $dateFrom, - $dateTo, - $group, - $idFeaturePrice, - $isSpecialDaysExists = false, - $jsonSpecialDays = "false" - ) { - $objFeaturePricing = new HotelRoomTypeFeaturePricing(); - if ($dateSelectionType == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { - return $objFeaturePricing->checkRoomTypeFeaturePriceExistance( - $roomTypeId, - $dateFrom, - $dateTo, - $group, - 'specific_date', - false, - $idFeaturePrice - ); - } elseif (isset($isSpecialDaysExists) && $isSpecialDaysExists && $jsonSpecialDays != "false") { - return $objFeaturePricing->checkRoomTypeFeaturePriceExistance( - $roomTypeId, - $dateFrom, - $dateTo, - $group, - 'special_day', - $jsonSpecialDays, - $idFeaturePrice - ); - } else { - return $objFeaturePricing->checkRoomTypeFeaturePriceExistance( - $roomTypeId, - $dateFrom, - $dateTo, - $group, - 'date_range', - false, - $idFeaturePrice - ); - } - } - public function processSave() { + if (!$this->loadObject(true)) { + return; + } + $idFeaturePrice = Tools::getValue('id_feature_price'); if (!isset($idFeaturePrice) || !$idFeaturePrice) { $idFeaturePrice = 0; } $enableFeaturePrice = Tools::getValue('enable_feature_price'); $roomTypeId = Tools::getValue('room_type_id'); - $dateFrom = Tools::getValue('date_from'); - $dateTo = Tools::getValue('date_to'); - $isSpecialDaysExists = Tools::getValue('is_special_days_exists'); - $specialDays = Tools::getValue('special_days'); $priceImpactWay = Tools::getValue('price_impact_way'); $priceImpactType = Tools::getValue('price_impact_type'); $impactValue = Tools::getValue('impact_value'); - $dateSelectionType = Tools::getValue('date_selection_type'); - $specificDate = date('Y-m-d', strtotime(Tools::getValue('specific_date'))); $groups = Tools::getValue('groupBox'); - $jsonSpecialDays = json_encode($specialDays); $defaultLangId = Configuration::get('PS_LANG_DEFAULT'); $createMultiple = Tools::getValue('create_multiple'); + $priceRules = Tools::getValue('advance_price_rule', array()); $objFeaturePricing = new HotelRoomTypeFeaturePricing(); if ($priceImpactWay == HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE) { $priceImpactType = HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE; @@ -448,39 +425,90 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController } } - if ($dateSelectionType == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { - $dateFrom = $specificDate; - $dateTo = date('Y-m-d', strtotime("+1 day", strtotime($specificDate))); - } else if ($dateSelectionType == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { - if ($dateFrom == '') { - $this->errors[] = $this->l('Please choose Date from for the advanced price rule.'); - } - if ($dateTo == '') { - $this->errors[] = $this->l('Please choose Date to for the advanced price rule.'); - } - $dateFrom = date('Y-m-d', strtotime($dateFrom)); - $dateTo = date('Y-m-d', strtotime($dateTo)); - if (!Validate::isDate($dateFrom)) { - $this->errors[] = $this->l('Invalid Date From.'); - } - if (!Validate::isDate($dateTo)) { - $this->errors[] = $this->l('Invalid Date To.'); - } - if ($dateTo < $dateFrom) { - $this->errors[] = $this->l('Date To cannot be smaller than Date From.'); - } - if ($isSpecialDaysExists) { - if (!isset($specialDays) || !$specialDays) { + $rowsToHighlight = []; + if (!$priceRules) { + $this->errors[] = $this->l('Atleast one rule is required while creating advance price rule.'); + } else { + foreach ($priceRules as $priceRuleKey => $priceRule) { + if (!$priceRule['is_special_days_exists']) { + unset($priceRules[$priceRuleKey]['special_days']); + } + if ($priceRule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { + if ($priceRule['specific_date']) { + $priceRules[$priceRuleKey]['date_from'] = $priceRule['specific_date']; + $priceRules[$priceRuleKey]['date_to'] = date('Y-m-d', strtotime("+1 day", strtotime($priceRule['specific_date']))); + unset($priceRules[$priceRuleKey]['specific_date']); + } else { + $rowsToHighlight[] = $priceRuleKey; + $this->errors = $this->l('Specific Date is missing for advance price rule'); + } + } else if ($priceRule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { + if ($priceRule['date_from'] == '') { + $rowsToHighlight[] = $priceRuleKey; + $this->errors[] = $this->l('Dates are invalid in some rules'); + } else if ($priceRule['date_to'] == '') { + $this->errors[] = $this->l('Dates are invalid in some rules'); + $rowsToHighlight[] = $priceRuleKey; + } + + $dateFrom = date('Y-m-d', strtotime($priceRule['date_from'])); + $dateTo = date('Y-m-d', strtotime($priceRule['date_to'])); + if (!Validate::isDate($dateFrom)) { + $this->errors[] = $this->l('Dates are invalid in some rules'); + $rowsToHighlight[] = $priceRuleKey; + } + if (!Validate::isDate($dateTo)) { + $this->errors[] = $this->l('Dates are invalid in some rules'); + } + if ($dateTo < $dateFrom) { + $this->errors[] = $this->l('Dates are invalid in some rules'); + } + if ($priceRule['is_special_days_exists']) { + if (!isset($priceRule['special_days']) || !$priceRule['special_days']) { + $this->errors[] = $this->l('Special days are missing for price rule having restrict to week days'); + $rowsToHighlight[] = $priceRuleKey; + } + } + unset($priceRules[$priceRuleKey]['specific_date']); + } else { + unset($priceRules[$priceRuleKey]); + } + + if ($priceRule['is_special_days_exists'] && empty($priceRule['special_days'])) { + $rowsToHighlight[] = $priceRuleKey; $this->errors[] = $this->l('Please select at least one day for week days restriction.'); } - } - } else { - if ($specificDate == '') { - $this->errors[] = $this->l('Please choose Date from for the advanced price rule.'); - } - $specificDate = date('Y-m-d', strtotime($specificDate)); - if (!Validate::isDate($specificDate)) { - $this->errors[] = $this->l('Invalid Date From.'); + + foreach ($priceRules as $ruleKey => $rule) { + if ($priceRuleKey != $ruleKey) { + if ($rule['date_selection_type'] == $priceRule['date_selection_type']) { + if ($rule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { + if (strtotime($rule['date_from']) != strtotime($priceRule['date_from'])) { + continue; + } else { + $this->errors[] = $this->l('Some dates are conflicting. Please check and reselect the dates.'); + $rowsToHighlight[] = $priceRuleKey; + } + } else if ($rule['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { + if (((strtotime($priceRule['date_from']) < strtotime($rule['date_from'])) && (strtotime($priceRule['date_to']) <= strtotime($rule['date_from']))) || ((strtotime($priceRule['date_from']) > strtotime($rule['date_from'])) && (strtotime($priceRule['date_from']) >= strtotime($rule['date_to'])))) { + continue; + } else { + if ($priceRule['is_special_days_exists'] && $rule['is_special_days_exists']) { + if (!empty($priceRule['special_days']) && !empty($rule['special_days'])) { + if (array_intersect($priceRule['special_days'], $rule['special_days'])) { + $this->errors[] = $this->l('Some days are conflicting. Please check and update the special days.'); + $rowsToHighlight[] = $priceRuleKey; + } + } + } else { + $this->errors[] = $this->l('Some dates are conflicting. Please check and reselect the date ranges.'); + $rowsToHighlight[] = $priceRuleKey; + } + } + } + } + } + } } } @@ -494,43 +522,34 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController $this->errors[] = $this->l('Please select at least one group for the group access'); } - $isPlanTypeExists = 0; - if ($isSpecialDaysExists && $jsonSpecialDays == 'false') { - $this->errors[] = $this->l('Please select at least one day for week days restriction.'); - } - - if (empty($this->errors)) { - foreach ($roomTypeIds as $idRoomType) { - $isPlanTypeExists = $this->validateExistingFeaturePrice( - $dateSelectionType, + $duplicatePriceRuleKey = 0; + if (empty($this->errors) && $enableFeaturePrice) { + $objFeaturePricing = new HotelRoomTypeFeaturePricing(); + foreach ($roomTypeIds as $idRoomType) { + $duplicatePriceRuleKey = $this->object->validateExistingFeaturePrice( $idRoomType, - $dateFrom, - $dateTo, $groups, $idFeaturePrice, - $isSpecialDaysExists, - $jsonSpecialDays + $priceRules ); - if ($isPlanTypeExists) { + if ($duplicatePriceRuleKey) { + $rowsToHighlight = array_merge($duplicatePriceRuleKey, $rowsToHighlight); $objProduct = new Product((int) $idRoomType, false, $this->context->language->id); - $this->errors[] = sprintf($this->l('An advanced price rule already exists for "%s" for the selected date range. Please select a different date range.'), $objProduct->name); + $this->errors[] = sprintf($this->l('An advanced price rule already exists for "%s". Please update the restrictions to avoid duplication.'), $objProduct->name); } } } - if (!$isPlanTypeExists && !count($this->errors)) { + $rowsToHighlight = array_values($rowsToHighlight); + $this->context->smarty->assign('rowsToHighlight', $rowsToHighlight); + if (!($this->errors)) { if ($idFeaturePrice) { $objFeaturePricing = new HotelRoomTypeFeaturePricing($idFeaturePrice); } // lang fields - $objFeaturePricing->date_selection_type = $dateSelectionType; - $objFeaturePricing->date_from = $dateFrom; - $objFeaturePricing->date_to = $dateTo; $objFeaturePricing->impact_way = $priceImpactWay; - $objFeaturePricing->is_special_days_exists = $isSpecialDaysExists; - $objFeaturePricing->special_days = $jsonSpecialDays; $objFeaturePricing->impact_type = $priceImpactType; $objFeaturePricing->impact_value = $impactValue; $objFeaturePricing->active = $enableFeaturePrice; @@ -543,6 +562,7 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController $objFeaturePricing->id_product = $idRoomType; $objFeaturePricing->feature_price_name = $featurePricingName[$idRoomType]; $objFeaturePricing->add(); + $objFeaturePricing->saveUpdateFeaturePrices($objFeaturePricing->id, $priceRules); } Tools::redirectAdmin(self::$currentIndex.'&conf=3&token='.$this->token); @@ -550,14 +570,16 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController $objFeaturePricing->feature_price_name = $featurePricingName[$roomTypeId]; } + $conf = $idFeaturePrice ? 4 : 3; if ($objFeaturePricing->save()) { + $objFeaturePricing->saveUpdateFeaturePrices($objFeaturePricing->id, $priceRules); if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) { Tools::redirectAdmin( self::$currentIndex.'&id_feature_price='.(int) $objFeaturePricing->id. - '&update'.$this->table.'&conf=4&token='.$this->token + '&update'.$this->table.'&conf='.$conf.'&token='.$this->token ); } else { - Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token); + Tools::redirectAdmin(self::$currentIndex.'&conf='.$conf.'&token='.$this->token); } } else { $this->errors[] = $this->l('Some error occured while saving advanced price rule.'); @@ -607,8 +629,14 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController Media::addJsDef(array( 'date_selection_types' => array( - 'range' => HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE, - 'specific' => HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC, + 'range' => array( + 'value' => HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE, + 'title' => $this->l('Date Range', null, true) + ), + 'specific' => array( + 'value' => HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC, + 'title' => $this->l('Specific Date', null, true) + ), ), 'impact_ways' => array( 'decrease' => HotelRoomTypeFeaturePricing::IMPACT_WAY_DECREASE, @@ -619,6 +647,17 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController 'percentage' => HotelRoomTypeFeaturePricing::IMPACT_TYPE_PERCENTAGE, 'fixed' => HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE, ), + 'week_days' => $this->getWeekDays(), + 'priceRuleHeadingText' => $this->l('Price rule restriction', null, true), + 'dateSelectionTitle' => $this->l('Date Selection type', null, true), + 'specificDateText' => $this->l('Specific Date', null, true), + 'dateFromText' => $this->l('Date From', null, true), + 'dateToText' => $this->l('Date to', null, true), + 'yesText' => $this->l('Yes', null, true), + 'noText' => $this->l('No', null, true), + 'specialDaysText' => $this->l('Restrict to Week Days', null, true), + 'weekDaysText' => $this->l('Select Week Days', null, true), + 'specialDaysTooltipText' => $this->l('Enable this option to restrict this rule to specific week days (for example, weekends) of the selected date range. If disabled, rule will be applicable to all week days.', null, true) )); $this->addCSS(_MODULE_DIR_.'hotelreservationsystem/views/css/HotelReservationAdmin.css'); diff --git a/modules/hotelreservationsystem/define.php b/modules/hotelreservationsystem/define.php index 78316bc6d..e6631fc70 100644 --- a/modules/hotelreservationsystem/define.php +++ b/modules/hotelreservationsystem/define.php @@ -32,6 +32,7 @@ require_once 'classes/HotelOrderRefundRules.php'; require_once 'classes/HotelOrderRestrictDate.php'; require_once 'classes/HotelHelper.php'; require_once 'classes/HotelRoomTypeFeaturePricing.php'; +require_once 'classes/HotelRoomTypeFeaturePricingRule.php'; require_once 'classes/ChannelOrderPayment.php'; require_once 'classes/HotelBookingDemands.php'; diff --git a/modules/hotelreservationsystem/hotelreservationsystem.php b/modules/hotelreservationsystem/hotelreservationsystem.php index 2a181cdf3..e1199845e 100644 --- a/modules/hotelreservationsystem/hotelreservationsystem.php +++ b/modules/hotelreservationsystem/hotelreservationsystem.php @@ -398,8 +398,7 @@ class HotelReservationSystem extends Module } // delete the feature prices of the room type - $objRoomTypeFeaturePricing = new HotelRoomTypeFeaturePricing(); - $objRoomTypeFeaturePricing->deleteFeaturePriceByIdProduct($idProduct); + HotelRoomTypeFeaturePricing::deleteFeaturePrices(false, $idProduct); // delete the disable dates (temporary inactive status) of the room type $objRoomDisableDates = new HotelRoomDisableDates(); diff --git a/modules/hotelreservationsystem/views/css/HotelReservationAdmin.css b/modules/hotelreservationsystem/views/css/HotelReservationAdmin.css index 6b2ee3587..588e8be99 100644 --- a/modules/hotelreservationsystem/views/css/HotelReservationAdmin.css +++ b/modules/hotelreservationsystem/views/css/HotelReservationAdmin.css @@ -614,4 +614,27 @@ body.adminhotelroomsbooking .ui-tooltip { #room-reallocation-modal .modal-body, #room-reallocation-modal .tab-content { padding: 15px; border: 1px solid #ddd -} \ No newline at end of file +} + +a.remove_advanced_price_rule { + position: absolute; + right: 5px; + top: -8px;} +#advanced_price_rule_group .panel.advanced_price_rule { + padding: 0px;} +#advanced_price_rule_group .advance_price_rule_header { + padding: 15px;} +#advanced_price_rule_group .advance_price_rule_header:hover { + cursor: pointer;} +.advance_price_rule_header i.icon-caret-down, +.advance_price_rule_header.collapsed i.icon-caret-up{ + display: none;} +.advance_price_rule_header.collapsed i.icon-caret-down{ + display: block;} +.advanced_price_rule_body { + border-top: 1px solid #d3d3d3;} +.advanced_price_rule_body .form-group:first-child { + margin-top: 15px;} +.error-border { + outline: rgb(210, 124, 130) solid 1px; + border-radius: 2px;} diff --git a/modules/hotelreservationsystem/views/js/HotelReservationAdmin.js b/modules/hotelreservationsystem/views/js/HotelReservationAdmin.js index fee7b3484..1502f6205 100644 --- a/modules/hotelreservationsystem/views/js/HotelReservationAdmin.js +++ b/modules/hotelreservationsystem/views/js/HotelReservationAdmin.js @@ -575,28 +575,37 @@ $(document).ready(function() { } }); - $('#date_selection_type').on('change', function() { - if ($('#date_selection_type').val() == date_selection_types.specific) { - $(".specific_date_type").show(200); - $(".date_range_type").hide(200); - $(".special_days_content").hide(200); - } else if ($('#date_selection_type').val() == date_selection_types.range) { - $(".specific_date_type").hide(200); - $(".date_range_type").show(200); - $(".special_days_content").show(200); + $(document).on('change', '.date_selection_type', function() { + let panelIndex = $(this).closest('.advanced_price_rule').data('advanced_price_rule_index'); + if ($('#date_selection_type_'+panelIndex).val() == date_selection_types.specific.value) { + $(".specific_date_type_"+panelIndex).show(200); + $(".date_range_type_"+panelIndex).hide(200); + $(".special_days_content_"+panelIndex).hide(200); + $('.week_days_'+panelIndex).hide(200); + } else if ($('#date_selection_type_'+panelIndex).val() == date_selection_types.range.value) { + $(".specific_date_type_"+panelIndex).hide(200); + $(".date_range_type_"+panelIndex).show(200); + $(".special_days_content_"+panelIndex).show(200); + if (parseInt($('[name="advance_price_rule['+panelIndex+'][is_special_days_exists]"]:checked').val())) { + $('.week_days_'+panelIndex).show(200); + } } else { - $(".specific_date_type").hide(200); - $(".date_range_type").show(200); - $(".special_days_content").show(200); + $(".specific_date_type_"+panelIndex).hide(200); + $(".date_range_type_"+panelIndex).show(200); + $(".special_days_content_"+panelIndex).show(200); + if (parseInt($('[name="advance_price_rule['+panelIndex+'][is_special_days_exists]"]:checked').val())) { + $('.week_days_'+panelIndex).show(200); + } } }); - $('[name="is_special_days_exists"]').on('change', function() { - if (parseInt($('[name="is_special_days_exists"]:checked').val())) { - $('.week_days').show(200); + $(document).on('change', '.is_special_days_exists', function() { + let panelIndex = $(this).closest('.advanced_price_rule').data('advanced_price_rule_index'); + if (parseInt($('[name="advance_price_rule['+panelIndex+'][is_special_days_exists]"]:checked').val())) { + $('.week_days_'+panelIndex).show(200); } else { - $('.week_days').hide(200); + $('.week_days_'+panelIndex).hide(200); } }); @@ -621,6 +630,95 @@ $(document).ready(function() { } }); + const dateToday = $.datepicker.formatDate('yy-mm-dd', new Date()); + $(document).on('click', '#add_more_dates_button', function() { + let dateSeletionOptions = $('').attr({'type':'checkbox', 'value': weekDayIndex, 'name': 'special_days'})) + .append($('

').text(weekDay))) + }); + let panelIndex = parseInt($('.advanced_price_rule').last().data('advanced_price_rule_index')); + if (isNaN(panelIndex)) { + panelIndex = 0; + } else { + panelIndex++; + } + + let panelElem = $('

').addClass('panel advanced_price_rule').attr('data-advanced_price_rule_index', panelIndex); + let idElem = $('').attr('type', 'hidden').attr('name', 'advance_price_rule['+panelIndex+'][id]') + let headerElem = $('
').addClass('row advance_price_rule_header collapsed').attr({'data-toggle':"collapse", 'data-target':"#advanced_price_rule_"+panelIndex}) + .append($('
').addClass('col-xs-8 col-sm-10').text(priceRuleHeadingText)) + .append($('
').addClass('col-xs-1 pull-right') + .append($('
').addClass('col-xs-8') + .append($('').addClass('btn btn-default remove_advanced_price_rule') + .append($('').append($('').addClass('icon-trash'))))) + .append($('
').addClass('col-xs-4') + .append($('').addClass('icon-caret-down')) + .append($('').addClass('icon-caret-up')))); + + let dateSelectionElem = $('
').addClass('form-group') + .append($('
').addClass('col-xs-6') + .append($(dateSeletionOptions).attr({'name': 'advance_price_rule['+panelIndex+'][date_selection_type]', 'id': 'date_selection_type_'+panelIndex}))); + + let specificDateElem = $('
').addClass('form-group specific_date_type_'+panelIndex).css('display', 'none') + .append($('
').addClass('col-xs-6') + .append($('').addClass('specific_date form-control datepicker-input') + .attr({type:'text', id: 'specific_date_'+panelIndex, name: 'advance_price_rule['+panelIndex+'][specific_date]', value: dateToday, readonly: 'readonly'}))); + + let dateFromElem = $('
').addClass('form-group date_range_type_'+panelIndex) + .append($('
').addClass('col-xs-6') + .append($('').addClass('feature_plan_date_from form-control datepicker-input') + .attr({type:'text', id: 'feature_plan_date_from_'+panelIndex, name: 'advance_price_rule['+panelIndex+'][date_from]', value: dateToday, readonly: 'readonly'}))); + + let dateToElem = $('
').addClass('form-group date_range_type_'+panelIndex) + .append($('
').addClass('col-xs-6') + .append($('').addClass('feature_plan_date_to form-control datepicker-input') + .attr({type:'text', id: 'feature_plan_date_to_'+panelIndex, name: 'advance_price_rule['+panelIndex+'][date_to]', value: dateToday, readonly: 'readonly'}))); + + let specialDaysElement = $('
').addClass('form-group special_days_content_'+panelIndex) + .append($('
').addClass('col-xs-6') + .append($('').addClass('switch prestashop-switch fixed-width-lg') + .append($('').attr({'type': 'radio', 'value': 1, 'name': 'advance_price_rule['+panelIndex+'][is_special_days_exists]', 'id': 'advance_price_rule['+panelIndex+'][is_special_days_exists_on]'}).addClass('is_special_days_exists')) + .append($('
').addClass('form-group week_days week_days_'+panelIndex) + .append($('
').addClass('col-xs-8 checkboxes-wrap').append($(weekDaysOptions).html())) + + let bodyElem = $('
').attr('id', 'advanced_price_rule_'+panelIndex).addClass('collapse advanced_price_rule_body') + .append(dateSelectionElem) + .append(specificDateElem) + .append(dateFromElem) + .append(dateToElem) + .append(specialDaysElement) + .append(specialDaysCheckBoxElem); + + panelElem.append(idElem).append(headerElem).append(bodyElem); + $('#advanced_price_rule_group').append($(panelElem).prop('outerHTML')); + $('#advanced_price_rule_group').find('.advanced_price_rule').last().find('.label-tooltip').tooltip(); + initDatePicker($('#advanced_price_rule_group').find('.advanced_price_rule').last()) + }); + + $(document).on('click', '.remove_advanced_price_rule', function(){ + $(this).closest('.advanced_price_rule').remove(); + }); + var ajax_pre_check_var = ''; $('.room_type_search_results_ul').hide(); @@ -676,49 +774,48 @@ $(document).ready(function() { $('.room_type_search_results_ul').empty().hide(); }); - $("#feature_plan_date_from").datepicker({ - showOtherMonths: true, - dateFormat: 'dd-mm-yy', - minDate: 0, - //for calender Css - beforeShowDay: function (date) { - return highlightDateBorder($("#feature_plan_date_from").val(), date); - }, - onSelect: function(selectedDate) { - let objDateToMin = $.datepicker.parseDate('dd-mm-yy', selectedDate); - objDateToMin.setDate(objDateToMin.getDate()); - - $('#feature_plan_date_to').datepicker('option', 'minDate', objDateToMin); - }, + $('.advanced_price_rule').each(function(){ + initDatePicker($(this)); }); + function initDatePicker(elem) { + $(elem).find(".feature_plan_date_from").datepicker({ + showOtherMonths: true, + dateFormat: 'yy-mm-dd', + minDate: 0, + onSelect: function(selectedDate) { + let objDateToMin = $.datepicker.parseDate('yy-mm-dd', selectedDate); + objDateToMin.setDate(objDateToMin.getDate()); + $(elem).find(".feature_plan_date_to").datepicker('option', 'minDate', objDateToMin); + }, + }); - $("#specific_date").datepicker({ - showOtherMonths: true, - dateFormat: 'dd-mm-yy', - minDate: 0, - }); + $(elem).find(".specific_date").datepicker({ + showOtherMonths: true, + dateFormat: 'yy-mm-dd', + minDate: 0, + }); - $("#feature_plan_date_to").datepicker({ - showOtherMonths: true, - dateFormat: 'dd-mm-yy', - beforeShow: function () { - let dateFrom = $('#feature_plan_date_from').val(); + $(elem).find(".feature_plan_date_to").datepicker({ + showOtherMonths: true, + dateFormat: 'yy-mm-dd', + beforeShow: function () { + let dateFrom = $(elem).find(".feature_plan_date_from").val(); + let objDateToMin = null; + if (typeof dateFrom != 'undefined' && dateFrom != '') { + objDateToMin = $.datepicker.parseDate('yy-mm-dd', dateFrom); + } else { + objDateToMin = new Date(); + } - let objDateToMin = null; - if (typeof dateFrom != 'undefined' && dateFrom != '') { - objDateToMin = $.datepicker.parseDate('dd-mm-yy', dateFrom); - } else { - objDateToMin = new Date(); + objDateToMin.setDate(objDateToMin.getDate()); + $(elem).find(".feature_plan_date_to").datepicker('option', 'minDate', objDateToMin); + }, + //for calender Css + beforeShowDay: function (date) { + return highlightDateBorder($("#feature_plan_date_to").val(), date); } - - objDateToMin.setDate(objDateToMin.getDate()); - $('#feature_plan_date_to').datepicker('option', 'minDate', objDateToMin); - }, - //for calender Css - beforeShowDay: function (date) { - return highlightDateBorder($("#feature_plan_date_to").val(), date); - } - }); + }); + } function highlightDateBorder(elementVal, date) { diff --git a/modules/hotelreservationsystem/views/templates/admin/_partials/feature_price_rules.tpl b/modules/hotelreservationsystem/views/templates/admin/_partials/feature_price_rules.tpl new file mode 100644 index 000000000..0e62baf1f --- /dev/null +++ b/modules/hotelreservationsystem/views/templates/admin/_partials/feature_price_rules.tpl @@ -0,0 +1,94 @@ + + diff --git a/modules/hotelreservationsystem/views/templates/admin/hotel_feature_prices_settings/helpers/form/form.tpl b/modules/hotelreservationsystem/views/templates/admin/hotel_feature_prices_settings/helpers/form/form.tpl index 875e3957b..8673ff040 100644 --- a/modules/hotelreservationsystem/views/templates/admin/hotel_feature_prices_settings/helpers/form/form.tpl +++ b/modules/hotelreservationsystem/views/templates/admin/hotel_feature_prices_settings/helpers/form/form.tpl @@ -81,7 +81,7 @@
{if isset($hotel_tree)}
#{l s='Id'}