public function ajaxProcessProductQuantity() { if (!Tools::getValue('actionQty')) { return Tools::jsonEncode(array('error' => $this->l('Undefined action'))); } $product = new Product((int) Tools::getValue('id_product'), true); switch (Tools::getValue('actionQty')) { case 'depends_on_stock': if (Tools::getValue('value') === false) { die(Tools::jsonEncode(array('error' => $this->l('Undefined value')))); } if ((int) Tools::getValue('value') != 0 && (int) Tools::getValue('value') != 1) { die(Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); } if (!$product->advanced_stock_management && (int) Tools::getValue('value') == 1) { die(Tools::jsonEncode(array('error' => $this->l('Not possible if advanced stock management is disabled. ')))); } if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int) Tools::getValue('value') == 1 && (Pack::isPack($product->id) && !Pack::allUsesAdvancedStockManagement($product->id) && ($product->pack_stock_type == 2 || $product->pack_stock_type == 1 || $product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 1 || Configuration::get('PS_PACK_STOCK_TYPE') == 2)))) { die(Tools::jsonEncode(array('error' => $this->l('You cannot use advanced stock management for this pack because') . '</br>' . $this->l('- advanced stock management is not enabled for these products') . '</br>' . $this->l('- you have chosen to decrement products quantities.')))); } StockAvailable::setProductDependsOnStock($product->id, (int) Tools::getValue('value')); break; case 'pack_stock_type': $value = Tools::getValue('value'); if ($value === false) { die(Tools::jsonEncode(array('error' => $this->l('Undefined value')))); } if ((int) $value != 0 && (int) $value != 1 && (int) $value != 2 && (int) $value != 3) { die(Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); } if ($product->depends_on_stock && !Pack::allUsesAdvancedStockManagement($product->id) && ((int) $value == 1 || (int) $value == 2 || (int) $value == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 1 || Configuration::get('PS_PACK_STOCK_TYPE') == 2))) { die(Tools::jsonEncode(array('error' => $this->l('You cannot use this stock management option because:') . '</br>' . $this->l('- advanced stock management is not enabled for these products') . '</br>' . $this->l('- advanced stock management is enabled for the pack')))); } Product::setPackStockType($product->id, $value); break; case 'out_of_stock': if (Tools::getValue('value') === false) { die(Tools::jsonEncode(array('error' => $this->l('Undefined value')))); } if (!in_array((int) Tools::getValue('value'), array(0, 1, 2))) { die(Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); } StockAvailable::setProductOutOfStock($product->id, (int) Tools::getValue('value')); break; case 'set_qty': $value = Tools::getValue('value'); if ($value !== false) { $value = $product->normalizeQty(trim($value)); } if ($value === false || !is_numeric($value)) { die(Tools::jsonEncode(array('error' => $this->l('Undefined value')))); } if (Tools::getValue('id_product_attribute') === false) { die(Tools::jsonEncode(array('error' => $this->l('Undefined id product attribute')))); } StockAvailable::setQuantity($product->id, (int) Tools::getValue('id_product_attribute'), $value); Hook::exec('actionProductUpdate', array('id_product' => (int) $product->id, 'product' => $product)); // Catch potential echo from modules $error = ob_get_contents(); if (!empty($error)) { ob_end_clean(); die(Tools::jsonEncode(array('error' => $error))); } break; case 'advanced_stock_management': if (Tools::getValue('value') === false) { die(Tools::jsonEncode(array('error' => $this->l('Undefined value')))); } if ((int) Tools::getValue('value') != 1 && (int) Tools::getValue('value') != 0) { die(Tools::jsonEncode(array('error' => $this->l('Incorrect value')))); } if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int) Tools::getValue('value') == 1) { die(Tools::jsonEncode(array('error' => $this->l('Not possible if advanced stock management is disabled. ')))); } $product->setAdvancedStockManagement((int) Tools::getValue('value')); if (StockAvailable::dependsOnStock($product->id) == 1 && (int) Tools::getValue('value') == 0) { StockAvailable::setProductDependsOnStock($product->id, 0); } break; } die(Tools::jsonEncode(array('error' => false))); }
public function updateQty($quantity, $id_product, $id_product_attribute = null, $id_customization = false, $operator = 'up', $id_address_delivery = 0, Shop $shop = null, $auto_add_cart_rule = true, $id_cart_product = 0, $ext_prop_quantities = null, $ext_qty = 0) { if (!$shop) { $shop = Context::getContext()->shop; } if (Context::getContext()->customer->id) { if ($id_address_delivery == 0 && (int) $this->id_address_delivery) { // The $id_address_delivery is null, use the cart delivery address $id_address_delivery = $this->id_address_delivery; } elseif ($id_address_delivery == 0) { // The $id_address_delivery is null, get the default customer address $id_address_delivery = (int) Address::getFirstCustomerAddressId((int) Context::getContext()->customer->id); } elseif (!Customer::customerHasAddress(Context::getContext()->customer->id, $id_address_delivery)) { // The $id_address_delivery must be linked with customer $id_address_delivery = 0; } } //$quantity = (int)$quantity; $id_product = (int) $id_product; $id_product_attribute = (int) $id_product_attribute; $product = new Product($id_product, false, Configuration::get('PS_LANG_DEFAULT'), $shop->id); if ($id_product_attribute) { $combination = new Combination((int) $id_product_attribute); if ($combination->id_product != $id_product) { return false; } } $properties = $product->productProperties(); $quantity = $product->normalizeQty($quantity); /* If we have a product combination, the minimal quantity is set with the one of this combination */ if (!empty($id_product_attribute)) { $minimal_quantity = $product->attributeMinQty($id_product_attribute); } else { $minimal_quantity = $product->minQty(); } if (!Validate::isLoadedObject($product)) { die(Tools::displayError()); } if (isset(self::$_nbProducts[$this->id])) { unset(self::$_nbProducts[$this->id]); } if (isset(self::$_totalWeight[$this->id])) { unset(self::$_totalWeight[$this->id]); } Hook::exec('actionBeforeCartUpdateQty', array('cart' => $this, 'product' => $product, 'id_product_attribute' => $id_product_attribute, 'id_customization' => $id_customization, 'quantity' => $quantity, 'operator' => $operator, 'id_address_delivery' => $id_address_delivery, 'shop' => $shop, 'auto_add_cart_rule' => $auto_add_cart_rule)); if ($quantity <= 0) { return $this->deleteProduct($id_product, $id_product_attribute, (int) $id_customization, 0, $id_cart_product); } elseif (!$product->available_for_order || Configuration::get('PS_CATALOG_MODE') && !defined('_PS_ADMIN_DIR_')) { return false; } else { if ($id_cart_product == 0 && !PP::qtyPolicyLegacy($properties['pp_qty_policy'])) { $result = false; } else { /* Check if the product is already in the cart */ $result = $this->containsProduct($id_product, $id_product_attribute, (int) $id_customization, (int) $id_address_delivery, PP::productQtyPolicyLegacy($product) ? 0 : $quantity, $id_cart_product); } /* Update quantity if product already exist */ if ($result) { if ($operator == 'up' || $operator == 'update') { $sql = 'SELECT stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, IFNULL(stock.quantity_remainder, 0) as quantity_remainder FROM ' . _DB_PREFIX_ . 'product p ' . Product::sqlStock('p', $id_product_attribute, true, $shop) . ' WHERE p.id_product = ' . $id_product; $result2 = Db::getInstance()->getRow($sql); $product_qty = (int) $result2['quantity'] + (double) $result2['quantity_remainder']; // Quantity for product pack if (Pack::isPack($id_product)) { $product_qty = Pack::getQuantity($id_product, $id_product_attribute); } if ($operator == 'up') { $q = $id_cart_product > 0 || PP::qtyPolicyLegacy($properties['pp_qty_policy']) ? (int) $quantity : 1; $new_qty = PP::resolveQty((int) $result['quantity'] + $q, $result['quantity_fractional']); $new_min_qty = $properties['pp_ext'] == 1 ? (int) $result['quantity'] + $q : $new_qty; $qty = '+ ' . (int) $q; } else { $new_qty = $new_min_qty = $qty = $quantity; } if (!Product::isAvailableWhenOutOfStock((int) $result2['out_of_stock'])) { if ($new_qty > $product_qty) { return false; } } } else { if ($operator == 'down') { $q = $id_cart_product > 0 ? (int) $quantity : 1; $new_qty = PP::resolveQty((int) $result['quantity'] - $q, $result['quantity_fractional']); $new_min_qty = $properties['pp_ext'] == 1 ? (int) $result['quantity'] - $q : $new_qty; $qty = '- ' . (int) $q; if ($new_min_qty < $minimal_quantity && (PP::qtyPolicyLegacy($properties['pp_qty_policy'] || $properties['pp_ext'] == 1) ? $minimal_quantity > 1 : $new_qty > 0)) { return -1; } } else { return false; } } /* Delete product from cart */ if (($properties['pp_ext'] == 1 ? $new_min_qty : $new_qty) <= 0) { return $this->deleteProduct((int) $id_product, (int) $id_product_attribute, (int) $id_customization, $id_address_delivery, $id_cart_product); } else { if ($new_min_qty < $minimal_quantity) { return -1; } else { if ($operator == 'up' || $operator == 'down') { Db::getInstance()->execute(' UPDATE `' . _DB_PREFIX_ . 'cart_product` SET `quantity` = `quantity` ' . $qty . ', `date_add` = NOW() WHERE `id_cart_product` = ' . (int) $result['id_cart_product'] . ' LIMIT 1'); } else { Db::getInstance()->execute(' UPDATE `' . _DB_PREFIX_ . 'cart_product` SET `quantity_fractional` = ' . $qty . ', `date_add` = NOW() WHERE `id_cart_product` = ' . (int) $result['id_cart_product'] . ' LIMIT 1'); } } } $id_cart_product = (int) $result['id_cart_product']; } elseif ($operator == 'up') { $sql = 'SELECT stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, IFNULL(stock.quantity_remainder, 0) as quantity_remainder FROM ' . _DB_PREFIX_ . 'product p ' . Product::sqlStock('p', $id_product_attribute, true, $shop) . ' WHERE p.id_product = ' . $id_product; $result2 = Db::getInstance()->getRow($sql); // Quantity for product pack if (Pack::isPack($id_product)) { $result2['quantity'] = Pack::getQuantity($id_product, $id_product_attribute); } $total_quantity = PP::qtyPolicyLegacy($properties['pp_qty_policy']) ? $quantity : ($ext_prop_quantities !== null && $ext_qty > 0 ? $quantity * $ext_qty : $quantity); if (!Product::isAvailableWhenOutOfStock((int) $result2['out_of_stock'])) { if ($total_quantity > $result2['quantity'] + (PP::qtyPolicyFractional($properties['pp_qty_policy']) ? (double) $result2['quantity_remainder'] : 0)) { return false; } } if (PP::qtyPolicyFractional($properties['pp_qty_policy']) && $ext_prop_quantities !== null && $ext_qty > 0) { if ($ext_qty < $minimal_quantity) { return -1; } else { if ($total_quantity < $minimal_quantity) { return -1; } } } $result_add = Db::getInstance()->insert('cart_product', array('id_product' => (int) $id_product, 'id_product_attribute' => (int) $id_product_attribute, 'id_cart' => (int) $this->id, 'id_address_delivery' => (int) $id_address_delivery, 'id_shop' => $shop->id, 'quantity' => PP::qtyPolicyLegacy($properties['pp_qty_policy']) ? $quantity : ($ext_prop_quantities !== null && $ext_qty > 0 ? $ext_qty : 1), 'quantity_fractional' => PP::qtyPolicyLegacy($properties['pp_qty_policy']) ? 0 : $quantity, 'date_add' => date('Y-m-d H:i:s'))); if (!$result_add) { return false; } $id_cart_product = Db::getInstance()->Insert_ID(); if (count($ext_prop_quantities)) { $db = Db::getInstance(); foreach ($ext_prop_quantities as $index => $value) { $db->insert('pp_product_ext', array('id_cart_product' => (int) $id_cart_product, 'position' => (int) $index, 'quantity' => (double) $value)); } } } $this->last_icp = $id_cart_product; } // refresh cache of self::_products $this->_products = $this->getProducts(true); $this->update(); $context = Context::getContext()->cloneContext(); $context->cart = $this; Cache::clean('getContextualValue_*'); if ($auto_add_cart_rule) { CartRule::autoAddToCart($context); } if ($product->customizable) { return $this->_updateCustomizationQuantity($quantity, (int) $id_customization, (int) $id_product, (int) $id_product_attribute, (int) $id_address_delivery, $operator, $id_cart_product); } else { return true; } }