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 2030927fd..1a1a13f26 100644 --- a/classes/webservice/WebserviceSpecificManagementBookings.php +++ b/classes/webservice/WebserviceSpecificManagementBookings.php @@ -2930,38 +2930,29 @@ 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'); - - if ($objRoomTypeFeaturePricing->add()) { - return $objRoomTypeFeaturePricing->id; + if ($this->context->cart->id_currency != (int)Configuration::get('PS_CURRENCY_DEFAULT')) { + $currency = Currency::getCurrencyInstance($this->context->cart->id_currency); + $params['price'] = Tools::ps_round($params['price']/$currency->conversion_rate, 6); } - return false; + $params['name'] = 'Api-Booking-Price'; + $params['impact_type'] = HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE; + $params['impact_value'] = $params['price']/$numDays; + $params['is_special_days_exists'] = 0; + $params['special_days'] = json_encode(false); + $params['restrictions'] = array( + array( + 'date_from' => $params['date_from'], + 'date_to' => $params['date_to'] + ) + ); + + return HotelRoomTypeFeaturePricing::createRoomTypeFeaturePrice($params); } /** diff --git a/controllers/admin/AdminCartsController.php b/controllers/admin/AdminCartsController.php index 9559ba9c3..1bdbbf6e5 100644 --- a/controllers/admin/AdminCartsController.php +++ b/controllers/admin/AdminCartsController.php @@ -1021,28 +1021,25 @@ 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, + 'is_special_days_exists' => 0, + 'impact_way' => HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE, + 'impact_type' => HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE, + 'impact_value' => $price, + 'restrictions' => array( + array( + 'date_from' => $date_from, + 'date_to' => $date_to + ) + ) + ) + ); - $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..d2819efca 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,26 @@ 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, + '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'], + 'restrictions' => array( + array( + 'date_from' => date('Y-m-d', strtotime($dateFrom)), + 'date_to' => date('Y-m-d', strtotime($dateTo)), + ) + ) + ) + ); } } } diff --git a/controllers/admin/AdminOrdersController.php b/controllers/admin/AdminOrdersController.php index 02d520d1b..41070e81b 100644 --- a/controllers/admin/AdminOrdersController.php +++ b/controllers/admin/AdminOrdersController.php @@ -4816,7 +4816,7 @@ class AdminOrdersControllerCore extends AdminController $featurePriceParams = array( 'id_cart' => $this->context->cart->id, 'id_guest' => $this->context->cookie->id_guest, - 'price' => $product_informations['product_price_tax_excl'], + 'impact_value' => $product_informations['product_price_tax_excl'], 'id_product' => $product->id, ); } @@ -4870,8 +4870,13 @@ class AdminOrdersControllerCore extends AdminController // create feature price if needed 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); + $featurePriceParams['restrictions'] = array( + array( + 'date_from' => $date_from, + 'date_to' => $date_to + ) + ); + HotelRoomTypeFeaturePricing::createRoomTypeFeaturePrice($featurePriceParams); } } else { break; @@ -5720,11 +5725,15 @@ class AdminOrdersControllerCore extends AdminController 'id_guest' => $cart->id_guest, 'id_product' => $id_product, 'id_room' => $id_room, - 'price' => $room_unit_price, - 'date_from' => $new_date_from, - 'date_to' => $new_date_to + 'impact_value' => $room_unit_price, + 'restrictions' => array( + array( + '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 16221f169..81d23c6c4 100644 --- a/modules/hotelreservationsystem/classes/HotelBookingDetail.php +++ b/modules/hotelreservationsystem/classes/HotelBookingDetail.php @@ -1955,13 +1955,11 @@ class HotelBookingDetail extends ObjectModel $featurePriceParams = array( 'id_cart' => $context->cart->id, 'id_guest' => $context->cookie->id_guest, - 'price' => $newRoomPriceTaxExcl, + 'impact_value' => $newRoomPriceTaxExcl, 'id_product' => $idNewRoomType, ); } - $objServiceProductCartDetail = new ServiceProductCartDetail(); - $bookingParams = array( 'date_from' => $objOldHotelBooking->date_from, 'date_to' => $objOldHotelBooking->date_to, @@ -1994,11 +1992,13 @@ class HotelBookingDetail extends ObjectModel // create feature price if needed if ($createFeaturePrice) { $featurePriceParams['id_room'] = $roomInfo['id_room']; - $featurePriceParams = array_merge( - $featurePriceParams, - array('date_from' => $objOldHotelBooking->date_from, 'date_to' => $objOldHotelBooking->date_to) + $featurePriceParams['restrictions'] = array( + 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 ec7d2efbe..bcb120674 100644 --- a/modules/hotelreservationsystem/classes/HotelCartBookingData.php +++ b/modules/hotelreservationsystem/classes/HotelCartBookingData.php @@ -1434,7 +1434,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, @@ -1444,10 +1444,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_restriction` 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; } @@ -1463,8 +1465,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_restriction` 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; } @@ -1473,9 +1477,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_restriction` 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']); @@ -1489,9 +1495,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_restriction` 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..d103e1576 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_restriction` ( + `id_feature_price_restriction` 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_restriction`) + ) 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_restriction`, `'._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 6c839aa39..ca621a1fd 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'), + 'restrictions' => array( + 'resource' => 'price_rule', + 'getter' => 'getWsFeaturePriceRestriction', + 'setter' => 'setWsFeaturePriceRestriction', + 'fields' => array( + 'id' => array(), + 'date_from' => array(), + 'date_to' => array(), + 'date_selection_type' => array(), + 'is_special_days_exists' => array(), + 'special_days' => array(), + ), + ), ) ); @@ -123,117 +126,110 @@ class HotelRoomTypeFeaturePricing extends ObjectModel { // first call to delete all the group entries $this->cleanGroups(); + $objFeaturePriceRestriction = new HotelRoomTypeFeaturePricingRestriction(); + if ($existingFeaturePrices = $objFeaturePriceRestriction->getRestrictionsByIdFeaturePrice($this->id)) { + $existingFeaturePrices = array_column($existingFeaturePrices, 'id_feature_price_restriction', 'id_feature_price_restriction'); + $objFeaturePriceRestriction->deleteFeaturePriceRestrictionsById($existingFeaturePrices); + } + 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` <= \''.pSQL($date_to).'\' AND `date_to` >= \''.pSQL($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, - $groups, - $type = 'date_range', - $current_Special_days = false, - $id_feature_price = 0 + public function getFeaturePrices( + $idRoomType, + $restrictions = array(), + $groups = array(), + $skipFeaturePriceId = null, + $active = null ) { - $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_restriction` 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` '.($groups ? ' AND rtfpg.`id_group` IN ('.pSQL(implode(', ',$groups)).')' : ' ' ).') + WHERE 1 '.( !is_null($active) ? ' AND rtfp.`active`= '.(int) $active: ' ').' ' .(!is_null($skipFeaturePriceId) ? ' AND rtfpr.`id_feature_price`!='.(int) $skipFeaturePriceId : ' '); + $sqlWhere = ''; + if ($restrictions && is_array($restrictions)) { + foreach ($restrictions as $restriction) { + if ($sqlWhere != '') { + $sqlWhere .= ' OR '; + } + + $dateFrom = date('Y-m-d', strtotime($restriction['date_from'])); + $dateTo = date('Y-m-d', strtotime($restriction['date_to'])); + if ($restriction['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 ($restriction['date_selection_type'] == self::DATE_SELECTION_TYPE_RANGE) { + if ($restriction['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 saveFeaturePriceRestrictions($idFeaturePrice, $restrictions) + { + $res = true; + $objFeaturePriceRestriction = new HotelRoomTypeFeaturePricingRestriction(); + if ($existingFeaturePrices = $objFeaturePriceRestriction->getRestrictionsByIdFeaturePrice($idFeaturePrice)) { + $existingFeaturePrices = array_column($existingFeaturePrices, 'id_feature_price_restriction', 'id_feature_price_restriction'); + } + + if ($restrictions) { + foreach ($restrictions as $featurePriceRule) { + if (isset($featurePriceRule['id']) && in_array($featurePriceRule['id'], $existingFeaturePrices)) { + $objFeaturePriceRestriction = new HotelRoomTypeFeaturePricingRestriction($featurePriceRule['id']); + unset($existingFeaturePrices[$featurePriceRule['id']]); + } else { + $objFeaturePriceRestriction = new HotelRoomTypeFeaturePricingRestriction(); + } + + $objFeaturePriceRestriction->id_feature_price = $idFeaturePrice; + $objFeaturePriceRestriction->date_from = $featurePriceRule['date_from']; + $objFeaturePriceRestriction->date_to = $featurePriceRule['date_to']; + $objFeaturePriceRestriction->date_selection_type = isset($featurePriceRule['date_selection_type']) ? $featurePriceRule['date_selection_type'] : HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE; + $objFeaturePriceRestriction->special_days = json_encode(array()); + if ($objFeaturePriceRestriction->date_selection_type == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE + && isset($featurePriceRule['is_special_days_exists']) && $featurePriceRule['is_special_days_exists'] + ) { + $objFeaturePriceRestriction->is_special_days_exists = $featurePriceRule['is_special_days_exists']; + if (isset($featurePriceRule['is_special_days_exists']) + && $featurePriceRule['is_special_days_exists'] + && isset($featurePriceRule['special_days']) + && $featurePriceRule['special_days'] + ) { + $objFeaturePriceRestriction->special_days = json_encode($featurePriceRule['special_days']); + } + } else { + $objFeaturePriceRestriction->is_special_days_exists = 0; + } + + $res &= $objFeaturePriceRestriction->save(); + } + } + + if ($existingFeaturePrices) { + $res &= $objFeaturePriceRestriction->deleteFeaturePriceRestrictionsById($existingFeaturePrices); + } + + return $res; } /** @@ -309,9 +305,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 +487,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_restriction` 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 +543,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_restriction` 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) { @@ -576,7 +576,7 @@ class HotelRoomTypeFeaturePricing extends ObjectModel /** * Deletes groups entries in the table. Send id_group if you want to delete entries by group i.e. when group deletes * @param integer $idGroup - * @return void + * @return bool */ public function cleanGroups($idGroup = 0) { @@ -640,25 +640,193 @@ class HotelRoomTypeFeaturePricing extends ObjectModel return true; } + public function getWsFeaturePriceRestriction() + { + return Db::getInstance()->executeS( + 'SELECT *, id_feature_price_restriction AS `id` FROM `'._DB_PREFIX_.'htl_room_type_feature_pricing_restriction` + WHERE `id_feature_price` ='.(int)$this->id.' ORDER BY `id_feature_price` ASC' + ); + + } + + public function setWsFeaturePriceRestriction($restrictions) + { + foreach ($restrictions as $restrictionKey => $restriction) { + if ($restriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE + && $restriction['is_special_days_exists'] + ) { + $specialDays = json_decode($restriction['special_days'], true); + $restrictions[$restrictionKey]['special_days'] = $specialDays; + } + } + + return $this->saveFeaturePriceRestrictions($this->id, $restrictions); + } + + public function getDuplicateRestrictions( + $roomTypeId, + $groups, + $skipFeaturePriceId, + $restrictions + ) { + $duplicateRestrictions = array(); + if ($existingFeturePrices = $this->getFeaturePrices( + $roomTypeId, + $restrictions, + $groups, + $skipFeaturePriceId, + true + )) { + foreach ($existingFeturePrices as $existingFeturePrice) { + foreach ($restrictions as $restrictionKey => $restriction) { + if ($restriction['date_selection_type'] == $existingFeturePrice['date_selection_type']) { + if ($restriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { + if (strtotime($restriction['date_from']) != strtotime($existingFeturePrice['date_from'])) { + continue; + } else { + $duplicateRestrictions[] = $restrictionKey; + } + } else if ($restriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { + if (((strtotime($existingFeturePrice['date_from']) < strtotime($restriction['date_from'])) && (strtotime($existingFeturePrice['date_to']) <= strtotime($restriction['date_from']))) || ((strtotime($existingFeturePrice['date_from']) > strtotime($restriction['date_from'])) && (strtotime($existingFeturePrice['date_from']) >= strtotime($restriction['date_to'])))) { + continue; + } else { + if ($existingFeturePrice['is_special_days_exists'] && $restriction['is_special_days_exists']) { + if (!empty($existingFeturePrice['special_days']) && !empty($restriction['special_days'])) { + $existingDays = json_decode($existingFeturePrice['special_days'], true); + if (array_intersect($existingDays, $restriction['special_days'])) { + $duplicateRestrictions[] = $restrictionKey; + } + } + } else { + $duplicateRestrictions[] = $restrictionKey; + } + } + } + } + } + } + } + + return $duplicateRestrictions; + } + 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); + $restrictions = array(); + $idGroups = array(); + if (isset($this->associations)) { + foreach ($this->associations->children() as $association) { + if ($association->getName() == 'restrictions') { + $assocItems = $association->children(); + foreach ($assocItems as $assocItem) { + /** @var SimpleXMLElement $assocItem */ + $fields = $assocItem->children(); + $entry = array(); + foreach ($fields as $fieldName => $fieldValue) { + $entry[$fieldName] = (string)$fieldValue; + } + + $restrictions[] = $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 ($restrictions) { + $hasError = false; + $weekDays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']; + // check for invalid special days + foreach ($restrictions as $restrictionKey => $restriction) { + if ($restriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { + if ($restriction['is_special_days_exists']) { + $specialDays = json_decode($restriction['special_days'], true); + $restrictions[$restrictionKey]['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 ($restrictions as $restrictionKey => $restriction) { + foreach ($restrictions as $priceRestrictionKey => $priceRestriction) { + if ($priceRestrictionKey != $restrictionKey) { + if ($priceRestriction['date_selection_type'] == $restriction['date_selection_type']) { + if ($priceRestriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { + if (strtotime($priceRestriction['date_from']) != strtotime($restriction['date_from'])) { + continue; + } else { + $message = Tools::displayError('You can not add conflicting dates.', true); + $hasError = true; + break; + } + } else if ($priceRestriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { + if (((strtotime($restriction['date_from']) < strtotime($priceRestriction['date_from'])) && (strtotime($restriction['date_to']) <= strtotime($priceRestriction['date_from']))) || ((strtotime($restriction['date_from']) > strtotime($priceRestriction['date_from'])) && (strtotime($restriction['date_from']) >= strtotime($priceRestriction['date_to'])))) { + continue; + } else { + if ($restriction['is_special_days_exists'] && $priceRestriction['is_special_days_exists']) { + if (!empty($restriction['special_days']) && !empty($priceRestriction['special_days'])) { + if (array_intersect($restriction['special_days'], $priceRestriction['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->getDuplicateRestrictions( + $this->id_product, + $idGroups, + $this->id, + $restrictions + ); + + 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 +839,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['impact_value']) ? $params['impact_value'] : 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->saveFeaturePriceRestrictions($objFeaturePricing->id, $params['restrictions']); + } + + return $objFeaturePricing->id; } } diff --git a/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricingRestriction.php b/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricingRestriction.php new file mode 100644 index 000000000..a1c0b9011 --- /dev/null +++ b/modules/hotelreservationsystem/classes/HotelRoomTypeFeaturePricingRestriction.php @@ -0,0 +1,80 @@ + +* @copyright 2010-2020 Webkul IN +* @license https://store.webkul.com/license.html +*/ + +class HotelRoomTypeFeaturePricingRestriction 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_restriction', + 'primary' => 'id_feature_price_restriction', + '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' => 'restrictions', + 'objectNodeName' => 'restriction', + 'fields' => array( + 'id_feature_price' => array( + 'xlink_resource' => array( + 'resourceName' => 'feature_prices', + ) + ), + ) + ); + + public function getRestrictionsByIdFeaturePrice($idFeaturePrice) + { + $sql = 'SELECT *, id_feature_price_restriction AS `id` FROM `'._DB_PREFIX_.$this->table.'` + WHERE `id_feature_price` ='.(int) $idFeaturePrice; + + return Db::getInstance()->executeS($sql); + } + + public function deleteFeaturePriceRestrictionsById($featurePriceRules) + { + $res = true; + if ($featurePriceRules) { + foreach ($featurePriceRules as $idFeaturePriceRules) { + $objFeaturePriceRule = new HotelRoomTypeFeaturePricingRestriction($idFeaturePriceRules); + $res &= $objFeaturePriceRule->delete(); + } + } + + return $res; + } + +} diff --git a/modules/hotelreservationsystem/controllers/admin/AdminHotelFeaturePricesSettings.php b/modules/hotelreservationsystem/controllers/admin/AdminHotelFeaturePricesSettings.php index 0635c619c..6bfbd4ee7 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 HotelRoomTypeFeaturePricingRestriction(); if (!$objFeaturePricing->active) { - if ($this->validateExistingFeaturePrice( - $objFeaturePricing->date_selection_type, + if ($this->object->getDuplicateRestrictions( $objFeaturePricing->id_product, - $objFeaturePricing->date_from, - $objFeaturePricing->date_to, $objFeaturePricing->getGroups($objFeaturePricing->id), $objFeaturePricing->id, - $objFeaturePricing->is_special_days_exists, - $objFeaturePricing->special_days - - + $objFeaturePriceRule->getRestrictionsByIdFeaturePrice($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 HotelRoomTypeFeaturePricingRestriction(); + if ($restrictions = $objFeaturePriceRule->getRestrictionsByIdFeaturePrice($objFeaturePrice->id)) { + foreach ($restrictions as $restrictionKey => $restriction) { + if ($restriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { + $restrictions[$restrictionKey]['specific_date'] = $restriction['date_from']; + unset($restrictions[$restrictionKey]['date_from']); + unset($restrictions[$restrictionKey]['date_to']); + } else if ($restriction['is_special_days_exists']) { + $restrictions[$restrictionKey]['special_days'] = json_decode($restriction['special_days'], true); + } + } + } + + $smartyVars['restrictions'] = $restrictions; $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'); + $restrictions = Tools::getValue('restriction', array()); $objFeaturePricing = new HotelRoomTypeFeaturePricing(); if ($priceImpactWay == HotelRoomTypeFeaturePricing::IMPACT_WAY_FIX_PRICE) { $priceImpactType = HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE; @@ -448,39 +425,91 @@ 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 (!$restrictions) { + $this->errors[] = $this->l('Atleast one restriction is required while creating advance price rule.'); + } else { + foreach ($restrictions as $restrictionKey => $restriction) { + if (!$restriction['is_special_days_exists']) { + unset($restrictions[$restrictionKey]['special_days']); + } + if ($restriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { + if ($restriction['specific_date']) { + $restrictions[$restrictionKey]['date_from'] = $restriction['specific_date']; + $restrictions[$restrictionKey]['date_to'] = date('Y-m-d', strtotime("+1 day", strtotime($restriction['specific_date']))); + } else { + $rowsToHighlight[] = $restrictionKey; + $this->errors = $this->l('Specific Date is missing for price rule restriction.'); + } + } else if ($restriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { + if ($restriction['date_from'] == '') { + $rowsToHighlight[] = $restrictionKey; + $this->errors[] = $this->l('Dates are invalid in price rule restriction.'); + } else if ($restriction['date_to'] == '') { + $this->errors[] = $this->l('Dates are invalid in price rule restriction'); + $rowsToHighlight[] = $restrictionKey; + } + + $dateFrom = date('Y-m-d', strtotime($restriction['date_from'])); + $dateTo = date('Y-m-d', strtotime($restriction['date_to'])); + if (!Validate::isDate($dateFrom)) { + $this->errors[] = $this->l('Dates are invalid in price rule restriction'); + $rowsToHighlight[] = $restrictionKey; + } + if (!Validate::isDate($dateTo)) { + $this->errors[] = $this->l('Dates are invalid in price rule restriction'); + } + if ($dateTo < $dateFrom) { + $this->errors[] = $this->l('Dates are invalid in price rule restriction'); + } + if ($restriction['is_special_days_exists']) { + if (!isset($restriction['special_days']) || !$restriction['special_days']) { + $this->errors[] = $this->l('Special days are missing for price rule having restrict to week days'); + $rowsToHighlight[] = $restrictionKey; + } + } + unset($restrictions[$restrictionKey]['specific_date']); + } else { + unset($restrictions[$restrictionKey]); + } + + if ($restriction['is_special_days_exists'] && empty($restriction['special_days'])) { + $rowsToHighlight[] = $restrictionKey; $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 ($restrictions as $restrictionKey => $restriction) { + foreach ($restrictions as $priceRestrictionKey => $priceRestriction) { + if ($restrictionKey != $priceRestrictionKey) { + if ($priceRestriction['date_selection_type'] == $restriction['date_selection_type']) { + if ($priceRestriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_SPECIFIC) { + if (strtotime($priceRestriction['specific_date']) != strtotime($restriction['specific_date'])) { + continue; + } else { + $this->errors[] = $this->l('Some dates are conflicting. Please check and reselect the dates.'); + $rowsToHighlight[] = $restrictionKey; + } + } else if ($priceRestriction['date_selection_type'] == HotelRoomTypeFeaturePricing::DATE_SELECTION_TYPE_RANGE) { + if (((strtotime($restriction['date_from']) < strtotime($priceRestriction['date_from'])) && (strtotime($restriction['date_to']) <= strtotime($priceRestriction['date_from']))) || ((strtotime($restriction['date_from']) > strtotime($priceRestriction['date_from'])) && (strtotime($restriction['date_from']) >= strtotime($priceRestriction['date_to'])))) { + continue; + } else { + if ($restriction['is_special_days_exists'] && $priceRestriction['is_special_days_exists']) { + if (!empty($restriction['special_days']) && !empty($priceRestriction['special_days'])) { + if (array_intersect($restriction['special_days'], $priceRestriction['special_days'])) { + $this->errors[] = $this->l('Some days are conflicting. Please check and update the special days.'); + $rowsToHighlight[] = $restrictionKey; + } + } + } else { + $this->errors[] = $this->l('Some dates are conflicting. Please check and reselect the date ranges.'); + $rowsToHighlight[] = $restrictionKey; + } + } + } + } + } + } } } @@ -494,43 +523,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, + $duplicateRestrictionKey = 0; + if (empty($this->errors) && $enableFeaturePrice) { + $objFeaturePricing = new HotelRoomTypeFeaturePricing(); + foreach ($roomTypeIds as $idRoomType) { + $duplicateRestrictionKey = $this->object->getDuplicateRestrictions( $idRoomType, - $dateFrom, - $dateTo, $groups, $idFeaturePrice, - $isSpecialDaysExists, - $jsonSpecialDays + $restrictions ); - if ($isPlanTypeExists) { + if ($duplicateRestrictionKey) { + $rowsToHighlight = array_merge($duplicateRestrictionKey, $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 +563,7 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController $objFeaturePricing->id_product = $idRoomType; $objFeaturePricing->feature_price_name = $featurePricingName[$idRoomType]; $objFeaturePricing->add(); + $objFeaturePricing->saveFeaturePriceRestrictions($objFeaturePricing->id, $restrictions); } Tools::redirectAdmin(self::$currentIndex.'&conf=3&token='.$this->token); @@ -550,14 +571,16 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController $objFeaturePricing->feature_price_name = $featurePricingName[$roomTypeId]; } + $conf = $idFeaturePrice ? 4 : 3; if ($objFeaturePricing->save()) { + $objFeaturePricing->saveFeaturePriceRestrictions($objFeaturePricing->id, $restrictions); 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 +630,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 +648,16 @@ class AdminHotelFeaturePricesSettingsController extends ModuleAdminController 'percentage' => HotelRoomTypeFeaturePricing::IMPACT_TYPE_PERCENTAGE, 'fixed' => HotelRoomTypeFeaturePricing::IMPACT_TYPE_FIXED_PRICE, ), + 'week_days' => $this->getWeekDays(), + '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 add restriction to specific week days (for example, weekends) of the selected date range.', 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..4d63a19a2 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/HotelRoomTypeFeaturePricingRestriction.php'; require_once 'classes/ChannelOrderPayment.php'; require_once 'classes/HotelBookingDemands.php'; diff --git a/modules/hotelreservationsystem/hotelreservationsystem.php b/modules/hotelreservationsystem/hotelreservationsystem.php index aef7e9e07..8da3931ea 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..5dd54412f 100644 --- a/modules/hotelreservationsystem/views/css/HotelReservationAdmin.css +++ b/modules/hotelreservationsystem/views/css/HotelReservationAdmin.css @@ -507,7 +507,7 @@ p.room_cat_data display: flex; } .week_days .checkboxes-wrap .day-wrap { - min-width: 50px; + min-width: 45px; } .room_type_search_results_ul { padding: 0px; @@ -614,4 +614,24 @@ 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 +} + +#advanced_price_rule_group .panel.advanced_price_rule { + padding: 10px 0px;} +#advanced_price_rule_group .advance_price_rule_header_container, .advanced_price_rule_body { + padding: 0px 20px;} +#advanced_price_rule_group .advance_price_rule_header_container:hover { + cursor: pointer;} +.advance_price_rule_header_container { + display: none;} +.advance_price_rule_header_container.shown{ + align-items: center; + display: flex;} +.special_days_heading{ + font-size: 11px; +} +.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..c6e6a80a2 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="restriction['+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="restriction['+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="restriction['+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,160 @@ $(document).ready(function() { } }); + const dateToday = $.datepicker.formatDate('yy-mm-dd', new Date()); + const tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + const dateTomorrow = $.datepicker.formatDate('yy-mm-dd', tomorrow); + $(document).find('.advanced_price_rule').each(function () { + udpateCollapseHeading($(this)); + }); + $(document).on('hide.bs.collapse', function(e) { + if ($(e.target).hasClass('advanced_price_rule_body')) { + let elem = $(e.target).closest('.advanced_price_rule'); + udpateCollapseHeading(elem); + $(elem).find('.advance_price_rule_header_container').addClass('shown'); + $(elem).find('.advanced_price_rule_body .advanced_price_rule_body_actions').hide(); + } + }); + + function udpateCollapseHeading(elem) { + let priceRuleHeadingText = ''; + let rowIndex = parseInt($(elem).data('advanced_price_rule_index')); + let selecteDateType = $('#date_selection_type_'+rowIndex).val(); + if (selecteDateType == date_selection_types.range.value) { + let dateFrom = $('#feature_plan_date_from_'+rowIndex).val(); + let dateTo = $('#feature_plan_date_to_'+rowIndex).val(); + priceRuleHeadingText = date_selection_types.range.title + ' ('+ dateFrom+ ' - '+ dateTo +')' + if (parseInt($('[name="restriction['+rowIndex+'][is_special_days_exists]"]:checked').val())) { + let special_days = []; + $('[name="restriction['+rowIndex+'][special_days][]"]').each(function(){ + if ($(this).prop('checked')) { + special_days.push($(this).parent().text().trim()); + } + }); + + if (special_days.length != 0) { + priceRuleHeadingText += '
(' + $(special_days).each(function(index, value) { + priceRuleHeadingText += value; + if (index != special_days.length-1) { + priceRuleHeadingText += ', '; + } + }); + priceRuleHeadingText += ')' + } + } + } else if (selecteDateType == date_selection_types.specific.value) { + priceRuleHeadingText = date_selection_types.specific.title; + let date = $('#specific_date_'+rowIndex).val(); + priceRuleHeadingText += ' ('+ date +')' + } + + $(elem).find('.advance_price_rule_header').html(priceRuleHeadingText); + } + + $(document).on('show.bs.collapse', function(e) { + if ($(e.target).hasClass('advanced_price_rule_body')) { + $(e.target).closest('.advanced_price_rule').find('.advance_price_rule_header_container').removeClass('shown'); + $(e.target).closest('.advanced_price_rule').find('.advanced_price_rule_body .advanced_price_rule_body_actions').show(); + } + }); + + $(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', 'restriction['+panelIndex+'][id]') + let headerElem = $('
').addClass('row advance_price_rule_header_container advance_price_rule_collapse').attr({'data-toggle':"collapse", 'data-target':"#advanced_price_rule_"+panelIndex}) + .append($('
').addClass('col-xs-9 advance_price_rule_header')) + .append($('
').addClass('col-xs-3') + .append($('
').addClass('col-xs-offset-7 col-xs-2') + .append($('').addClass('btn btn-default remove_advanced_price_rule') + .append($('').append($('').addClass('icon-trash'))))) + .append($('
').addClass('col-xs-offset-1 col-xs-2') + .append($('').addClass('btn btn-default') + .append($('').addClass('icon-caret-down'))))); + + let dateSelectionElem = $('
').addClass('form-group') + .append($('
').addClass('col-xs-5') + .append($(dateSeletionOptions).attr({'name': 'restriction['+panelIndex+'][date_selection_type]', 'id': 'date_selection_type_'+panelIndex}))) + .append($('
').addClass('col-xs-3 advanced_price_rule_body_actions') + .append($('
').addClass('col-xs-offset-7 col-xs-2') + .append($('').addClass('btn btn-default remove_advanced_price_rule') + .append($('').append($('').addClass('icon-trash'))))) + .append($('
').addClass('col-xs-offset-1 col-xs-2') + .append($('').addClass('btn btn-default').attr({'data-toggle':"collapse", 'data-target':"#advanced_price_rule_"+panelIndex}) + .append($('').addClass('icon-caret-up'))))); + + let specificDateElem = $('
').addClass('form-group specific_date_type_'+panelIndex).css('display', 'none') + .append($('
').addClass('col-xs-5') + .append($('').addClass('specific_date form-control datepicker-input') + .attr({type:'text', id: 'specific_date_'+panelIndex, name: 'restriction['+panelIndex+'][specific_date]', value: dateToday, readonly: 'readonly'}))); + + let dateFromElem = $('
').addClass('form-group date_range_type_'+panelIndex) + .append($('
').addClass('col-xs-5') + .append($('').addClass('feature_plan_date_from form-control datepicker-input') + .attr({type:'text', id: 'feature_plan_date_from_'+panelIndex, name: 'restriction['+panelIndex+'][date_from]', value: dateToday, readonly: 'readonly'}))); + + let dateToElem = $('
').addClass('form-group date_range_type_'+panelIndex) + .append($('
').addClass('col-xs-5') + .append($('').addClass('feature_plan_date_to form-control datepicker-input') + .attr({type:'text', id: 'feature_plan_date_to_'+panelIndex, name: 'restriction['+panelIndex+'][date_to]', value: dateTomorrow, readonly: 'readonly'}))); + + let specialDaysElement = $('
').addClass('form-group special_days_content_'+panelIndex) + .append($('
').addClass('col-xs-5') + .append($('').addClass('switch prestashop-switch fixed-width-lg') + .append($('').attr({'type': 'radio', 'value': 1, 'name': 'restriction['+panelIndex+'][is_special_days_exists]', 'id': 'restriction['+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('in 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 +839,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..d3d351061 --- /dev/null +++ b/modules/hotelreservationsystem/views/templates/admin/_partials/feature_price_rules.tpl @@ -0,0 +1,126 @@ +{** +* 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 this module to a newer +* versions in the future. If you wish to customize this module 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 +*} + +
+ + +
+
+ +
+ +
+
+
+ + + +
+
+ + + +
+
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ + + + + + + +
+
+ +
+ +
+ {foreach $week_days as $dayVal => $day} +
+ +

{$day}

+
+ {/foreach} +
+
+
+
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..30a613ea2 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'}