diff --git a/classes/Product.php b/classes/Product.php
index 33d169e23..911610672 100644
--- a/classes/Product.php
+++ b/classes/Product.php
@@ -77,6 +77,9 @@ class ProductCore extends ObjectModel
/** @var bool allow order for multiple quantities */
public $allow_multiple_quantity;
+ /** @var bool max allowed quantities */
+ public $max_quantity;
+
/** @var string available_now */
public $available_now;
@@ -308,6 +311,7 @@ class ProductCore extends ObjectModel
'ecotax' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'),
'minimal_quantity' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'),
'allow_multiple_quantity' => array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
+ 'max_quantity' => array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'),
'price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'required' => true),
'wholesale_price' => array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'),
'unity' => array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isString'),
diff --git a/controllers/admin/AdminOrdersController.php b/controllers/admin/AdminOrdersController.php
index f928ddfc8..7ff79c153 100644
--- a/controllers/admin/AdminOrdersController.php
+++ b/controllers/admin/AdminOrdersController.php
@@ -5268,6 +5268,8 @@ class AdminOrdersControllerCore extends AdminController
if ($objProduct->allow_multiple_quantity) {
if (!Validate::isUnsignedInt($qty)) {
$this->errors[] = Tools::displayError('The quantity code you\'ve entered is invalid.');
+ // } elseif ($objProduct->max_quantity && $qty > $objProduct->max_quantity) {
+ // $this->errors[] = Tools::displayError(sprintf('cannot add more than %d quantity.', $objProduct->max_quantity));
}
} else {
$qty = 1;
diff --git a/controllers/front/CartController.php b/controllers/front/CartController.php
index a2444c921..69ce2e3e8 100644
--- a/controllers/front/CartController.php
+++ b/controllers/front/CartController.php
@@ -395,16 +395,26 @@ class CartControllerCore extends FrontController
if (Tools::getValue('op', 'up') == 'up') {
if ($total_available_rooms < $req_rm) {
die(json_encode(array('status' => 'unavailable_quantity', 'avail_rooms' => $total_available_rooms)));
- } else {
- // validate normal products if available
- if ($serviceProducts) {
- $objRoomTypeServiceProduct = new RoomTypeServiceProduct();
- foreach ($serviceProducts as $key => $standartProduct) {
- if (!$objRoomTypeServiceProduct->isRoomTypeLinkedWithProduct($this->id_product, $standartProduct['id_product'])) {
- unset($serviceProducts[$key]);
+ } else {
+ // validate service products if available
+ if ($serviceProducts) {
+ $objRoomTypeServiceProduct = new RoomTypeServiceProduct();
+ foreach ($serviceProducts as $key => $serviceProduct) {
+ if (!$objRoomTypeServiceProduct->isRoomTypeLinkedWithProduct($this->id_product, $serviceProduct['id_product'])) {
+ unset($serviceProducts[$key]);
+ } else {
+ if (Validate::isLoadedObject($objServiceProduct = new Product($serviceProduct['id_product']))) {
+ if (!$objServiceProduct->allow_multiple_quantity && $serviceProduct['quantity'] > 1) {
+ $serviceProducts[$key]['quantity'] = 1;
+ } else if ($objServiceProduct->max_quantity && $objServiceProduct->max_quantity < $serviceProduct['quantity'] ) {
+ $serviceProducts[$key]['quantity'] = $objServiceProduct->max_quantity;
+ }
+ } else {
+ $response['error'] = Tools::displayError('Service not Found');
}
}
}
+ }
}
}
} else {
@@ -621,6 +631,8 @@ class CartControllerCore extends FrontController
if ($objProduct->allow_multiple_quantity) {
if (!Validate::isUnsignedInt($qty)) {
$this->errors[] = Tools::displayError('The quantity you\'ve entered is invalid.');
+ } elseif ($objProduct->max_quantity && $qty > $objProduct->max_quantity) {
+ $this->errors[] = Tools::displayError(sprintf('cannot add more than %d quantity.', $objProduct->max_quantity));
}
} else {
$qty = 1;
diff --git a/controllers/front/ProductController.php b/controllers/front/ProductController.php
index 73808d9c9..74f8030fc 100644
--- a/controllers/front/ProductController.php
+++ b/controllers/front/ProductController.php
@@ -689,10 +689,22 @@ class ProductControllerCore extends FrontController
$serviceProductsPrice = 0;
if ($roomServiceProducts = json_decode($roomServiceProducts, true)) {
$objRoomTypeServiceProductPrice = new RoomTypeServiceProductPrice();
+ $objRoomTypeServiceProduct = new RoomTypeServiceProduct();
foreach ($roomServiceProducts as &$product) {
- $objProduct = new ProductCore($product['id_product'], false, $this->context->language->id);
- $product['name'] = $objProduct->name;
- $product['allow_multiple_quantity'] = $objProduct->allow_multiple_quantity;
+ if (!$objRoomTypeServiceProduct->isRoomTypeLinkedWithProduct($idProduct, $product['id_product'])) {
+ unset($product);
+ continue;
+ } else {
+ $objServiceProduct = new ProductCore($product['id_product'], false, $this->context->language->id);
+ if (!$objServiceProduct->allow_multiple_quantity && $product['quantity'] > 1) {
+ $product['quantity'] = 1;
+ } else if ($objServiceProduct->max_quantity && $objServiceProduct->max_quantity < $product['quantity'] ) {
+ $product['quantity'] = $objServiceProduct->max_quantity;
+ }
+
+ }
+ $product['name'] = $objServiceProduct->name;
+ $product['allow_multiple_quantity'] = $objServiceProduct->allow_multiple_quantity;
$productPrice = $objRoomTypeServiceProductPrice->getProductPrice($product['id_product'], $idProduct, $product['quantity'], $useTax);
$product['price'] = $productPrice;
$serviceProductsPrice += $productPrice;
@@ -1326,6 +1338,7 @@ class ProductControllerCore extends FrontController
$idProduct = Tools::getValue('id_product');
$idServiceProduct = Tools::getValue('service_product');
$addedServiceProduct = Tools::getValue('added_service_product');
+ $qty = Tools::getValue('qty');
if (Validate::isLoadedObject($objProduct = new Product($idProduct))) {
if (!Product::isBookingProduct($idProduct)) {
$response['error'] = Tools::displayError('Room Type info not Found');
@@ -1338,16 +1351,31 @@ class ProductControllerCore extends FrontController
} else {
if (Validate::isLoadedObject($objServiceProduct = new Product($idServiceProduct))) {
$response['success'] = true;
- if (!$objServiceProduct->allow_multiple_quantity && !empty($addedServiceProduct)) {
- if (!in_array($idServiceProduct, array_column($addedServiceProduct, 'id_product'))) {
+ if (!$objServiceProduct->allow_multiple_quantity) {
+ if (!empty($addedServiceProduct)) {
+ if (!in_array($idServiceProduct, array_column($addedServiceProduct, 'id_product'))) {
+ $response['add'] = true;
+ $response['msg'] = 'Service is added to cart.';
+ } else {
+ $response['msg'] = 'Service already added.';
+ }
+ } else {
$response['add'] = true;
$response['msg'] = 'Service is added to cart.';
- } else {
- $response['msg'] = 'Service already added.';
}
} else {
- $response['add'] = true;
- $response['msg'] = 'Service is added to cart.';
+ $totalQty = $qty;
+ if (!empty($addedServiceProduct)) {
+ if (($key = array_search($idServiceProduct, array_column($addedServiceProduct, 'id_product')))!== false) {
+ $totalQty += $addedServiceProduct[$key]['quantity'];
+ }
+ }
+ if ($objServiceProduct->max_quantity && $objServiceProduct->max_quantity < $totalQty ) {
+ $response['msg'] = Tools::displayError(sprintf('Cannot add more than %d quantity.', $objServiceProduct->max_quantity));
+ } else {
+ $response['add'] = true;
+ $response['msg'] = Tools::displayError('Service is added to cart.');
+ }
}
} else {
$response['error'] = Tools::displayError('Service not Found');
diff --git a/install/data/db_structure.sql b/install/data/db_structure.sql
index 5bc961640..07a2b4097 100644
--- a/install/data/db_structure.sql
+++ b/install/data/db_structure.sql
@@ -1519,6 +1519,7 @@ CREATE TABLE `PREFIX_product` (
`quantity` int(10) NOT NULL DEFAULT '0',
`minimal_quantity` int(10) unsigned NOT NULL DEFAULT '1',
`allow_multiple_quantity` tinyint(1) unsigned NOT NULL DEFAULT '1',
+ `max_quantity` int(10) unsigned NOT NULL DEFAULT '1',
`price` decimal(20,6) NOT NULL DEFAULT '0.000000',
`wholesale_price` decimal(20,6) NOT NULL DEFAULT '0.000000',
`unity` varchar(255) DEFAULT NULL,
@@ -1578,6 +1579,7 @@ CREATE TABLE IF NOT EXISTS `PREFIX_product_shop` (
`ecotax` decimal(17,6) NOT NULL DEFAULT '0.000000',
`minimal_quantity` int(10) unsigned NOT NULL DEFAULT '1',
`allow_multiple_quantity` tinyint(1) unsigned NOT NULL DEFAULT '1',
+ `max_quantity` int(10) unsigned NOT NULL DEFAULT '1',
`price` decimal(20,6) NOT NULL DEFAULT '0.000000',
`wholesale_price` decimal(20,6) NOT NULL DEFAULT '0.000000',
`unity` varchar(255) DEFAULT NULL,
diff --git a/js/admin/normal_products.js b/js/admin/normal_products.js
index abe3db07a..e15945f8b 100644
--- a/js/admin/normal_products.js
+++ b/js/admin/normal_products.js
@@ -449,6 +449,14 @@ product_tabs['Informations'] = new function(){
}
});
+ $('input[name=allow_multiple_quantity]').on('change', function(e) {
+ if ($(this).val() == 1) {
+ $('#max_quantity_container').show('fast');
+ } else {
+ $('#max_quantity_container').hide('fast');
+ }
+ });
+
$('#related_product_autocomplete_input')
.autocomplete('ajax_products_list.php?exclude_packs=0&excludeVirtuals=0&excludeIds='+id_product, {
minChars: 1,
diff --git a/themes/hotel-reservation-theme/_partials/cart_booking_demands.tpl b/themes/hotel-reservation-theme/_partials/cart_booking_demands.tpl
index 788ef2cb0..077c3f9fb 100644
--- a/themes/hotel-reservation-theme/_partials/cart_booking_demands.tpl
+++ b/themes/hotel-reservation-theme/_partials/cart_booking_demands.tpl
@@ -118,7 +118,7 @@
{$product['name']|escape:'html':'UTF-8'}
{if $product.allow_multiple_quantity}
-
+
diff --git a/themes/hotel-reservation-theme/_partials/service-products-list-row.tpl b/themes/hotel-reservation-theme/_partials/service-products-list-row.tpl
index f700c7720..e2474c0d6 100644
--- a/themes/hotel-reservation-theme/_partials/service-products-list-row.tpl
+++ b/themes/hotel-reservation-theme/_partials/service-products-list-row.tpl
@@ -50,7 +50,7 @@
{/if}
{if $product.allow_multiple_quantity && $product.available_for_order}
-
+
{if isset($product.quantity_added) && $product.quantity_added}{$product.quantity_added|escape:'html':'UTF-8'}{else}1{/if}
diff --git a/themes/hotel-reservation-theme/js/order-opc.js b/themes/hotel-reservation-theme/js/order-opc.js
index 7456edabe..23d5f7e26 100644
--- a/themes/hotel-reservation-theme/js/order-opc.js
+++ b/themes/hotel-reservation-theme/js/order-opc.js
@@ -468,8 +468,11 @@ $(document).ready(function()
$(document).on('click', '#rooms_extra_services .qty_up', function(e) {
e.preventDefault();
qtyfield = $(this).closest('.qty_container').find('input.qty');
- var currentVal = parseInt(qtyfield.val());
- qtyfield.val(currentVal + 1).trigger('focusout');
+ var newQuantity = parseInt(qtyfield.val()) + 1;
+ if (qtyfield.data('max_quantity') && qtyfield.data('max_quantity') < newQuantity) {
+ newQuantity = qtyfield.data('max_quantity');
+ }
+ qtyfield.val(newQuantity).trigger('focusout');
});
$(document).on('click', '#rooms_extra_services .qty_down', function(e) {
@@ -487,6 +490,9 @@ $(document).ready(function()
var qty_wntd = $(this).val();
if (qty_wntd == '' || !$.isNumeric(qty_wntd)) {
$(this).val(1);
+ }
+ if ($(this).data('max_quantity') && $(this).data('max_quantity') < qty_wntd) {
+ $(this).val(qtyfield.data('max_quantity'));
}
if ($(this).closest('.room_demand_block').find('.change_room_type_service_product').is(':checked')) {
updateServiceProducts($(this).closest('.room_demand_block').find('.change_room_type_service_product'));
diff --git a/themes/hotel-reservation-theme/js/product.js b/themes/hotel-reservation-theme/js/product.js
index 09a7cbdac..d2b8bb6fc 100644
--- a/themes/hotel-reservation-theme/js/product.js
+++ b/themes/hotel-reservation-theme/js/product.js
@@ -1108,9 +1108,12 @@ $(document).ready(function() {
$(document).on('click', '.service_product_qty_up', function(e) {
e.preventDefault();
qtyfield = $(this).closest('.qty_container').find('input.service_product_qty');
- var currentVal = parseInt(qtyfield.val());
- $(this).closest('.qty_container').find('.qty_count span').text(currentVal + 1);
- qtyfield.val(currentVal + 1);
+ var newQuantity = parseInt(qtyfield.val()) + 1;
+ if (qtyfield.data('max_quantity') && qtyfield.data('max_quantity') < newQuantity) {
+ newQuantity = qtyfield.data('max_quantity');
+ }
+ $(this).closest('.qty_container').find('.qty_count span').text(newQuantity);
+ qtyfield.val(newQuantity);
});
// The button to decrement the product value