From 3105fc5ddc24b4dcbc15a39b99d1679b0d623142 Mon Sep 17 00:00:00 2001 From: mDeflotte Date: Thu, 13 Oct 2011 15:58:29 +0000 Subject: [PATCH] // Add stock avaibility --- admin-dev/ajax.php | 17 + admin-dev/tabs/AdminProducts.php | 549 ++++++++++++++++++++++-------- classes/Cart.php | 7 +- classes/Category.php | 7 +- classes/Manufacturer.php | 13 +- classes/Product.php | 93 ++++- classes/ProductSale.php | 9 +- classes/Search.php | 20 +- classes/Supplier.php | 5 +- classes/stock/StockAvailable.php | 104 +++++- classes/stock/StockManager.php | 6 +- modules/mailalerts/mailalerts.php | 2 +- 12 files changed, 634 insertions(+), 198 deletions(-) diff --git a/admin-dev/ajax.php b/admin-dev/ajax.php index 31f10349d..ea0ea6084 100644 --- a/admin-dev/ajax.php +++ b/admin-dev/ajax.php @@ -83,6 +83,23 @@ if (Tools::isSubmit('ajaxProductManufacturers')) die('['.implode(',', $jsonArray).']'); } } + +if (Tools::isSubmit('ajaxProductQuantity')) +{ + require_once(dirname(__FILE__).'/tabs/AdminCatalog.php'); + $catalog = new AdminCatalog(); + $admin = new AdminProducts(); + + $languages = Language::getLanguages(false); + $defaultLanguage = (int)(Configuration::get('PS_LANG_DEFAULT')); + $product = new Product((int)(Tools::getValue('id_product'))); + if (!Validate::isLoadedObject($product)) + die (Tools::displayError('Product cannot be loaded')); + + AdminTab::$currentIndex = 'index.php?tab=AdminCatalog'; + echo $admin->ajaxProductQuantity($product); +} + if (Tools::isSubmit('ajaxReferrers')) { require('tabs/AdminReferrers.php'); diff --git a/admin-dev/tabs/AdminProducts.php b/admin-dev/tabs/AdminProducts.php index b6be9edcd..ee9be0dbc 100644 --- a/admin-dev/tabs/AdminProducts.php +++ b/admin-dev/tabs/AdminProducts.php @@ -555,15 +555,15 @@ class AdminProducts extends AdminTab Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact'), Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact'), Tools::getValue('attribute_unity') * Tools::getValue('attribute_unit_impact'), - Tools::getValue('attribute_ecotax'), - Tools::getValue('attribute_quantity'), - Tools::getValue('id_image_attr'), - Tools::getValue('attribute_reference'), - Tools::getValue('attribute_supplier_reference'), - Tools::getValue('attribute_ean13'), - Tools::getValue('attribute_default'), - Tools::getValue('attribute_location'), - Tools::getValue('attribute_upc')); + Tools::getValue('attribute_ecotax'), + Tools::getValue('attribute_quantity'), + Tools::getValue('id_image_attr'), + Tools::getValue('attribute_reference'), + Tools::getValue('attribute_supplier_reference'), + Tools::getValue('attribute_ean13'), + Tools::getValue('attribute_default'), + Tools::getValue('attribute_location'), + Tools::getValue('attribute_upc')); $this->updateDownloadProduct($product, 0, $id_product_attribute); } else @@ -1682,7 +1682,8 @@ class AdminProducts extends AdminTab

4. '.$this->l('Combinations').(isset($countAttributes) ? ' ('.$countAttributes.')' : '').'

5. '.$this->l('Features').'

6. '.$this->l('Customization').'

-

7. '.$this->l('Attachments').' ('.$countAttachments.')

'; +

7. '.$this->l('Attachments').' ('.$countAttachments.')

' + .$this->displayQuantities($obj); echo ' - - '.$this->l('When out of stock:').' - - getFieldValue($obj, 'out_of_stock')) == 0 ? 'checked="checked"' : '').'/> -
getFieldValue($obj, 'out_of_stock') == 1 ? 'checked="checked"' : '').'/> -
getFieldValue($obj, 'out_of_stock') == 2 ? 'checked="checked"' : '').'/> - -
@@ -3486,118 +3461,118 @@ class AdminProducts extends AdminTab '.$this->l('File:').' -
- -
-
- - - - - - - - - - + + + + + + +

'.$this->l('Format:').' JPG, GIF, PNG. '.$this->l('Filesize:').' '.($this->maxImageSize / 1000).''.$this->l('Kb max.').'

@@ -3685,6 +3660,284 @@ class AdminProducts extends AdminTab echo ' '; } + + + function displayQuantities($obj) + { + + // Get all id_product_atribute + $attributes = $obj->getAttributeCombinaisons($this->context->language->id); + if (empty($attributes)) + $attributes[] = array( + 'id_product_attribute' => 0, + 'attribute_name' => '' + ); + + // Get physical quantities & available quantities + $totalQuantity = 0; + $physicalQuantity = array(); + $availableQuantity = array(); + $productDesignation = array(); + foreach ($attributes as $attribute) + { + $physicalQuantity[$attribute['id_product_attribute']] = (int)rand(0, 100);//StockManagerFactory::getManager()->getProductPhysicalQuantities((int)$obj->id, $attribute['id_product_attribute']); + $totalQuantity += $physicalQuantity[$attribute['id_product_attribute']]; + + // @TODO + $availableQuantity[$attribute['id_product_attribute']] = StockAvailable::getStockAvailableForProduct((int)$obj->id, $attribute['id_product_attribute']); + + // Get all product designation + $productDesignation[$attribute['id_product_attribute']] = $obj->name[$this->context->language->id].' '.$attribute['attribute_name']; + } + + $return = ' +
+

8. '.$this->l('Quantities').'

+ + + + + + +
+ '.$this->l('Available stock in warehouses').' +
+
+

'.sprintf($this->l('There is %s quantities available in stock for this product'), ''.$totalQuantity.'').'

+ + + + + + +
+ + + + + + + + '; + foreach ($attributes as $attribute) + $return .= ' + + + + '; + $return .= ' + +
'.$this->l('Quantity').''.$this->l('Designation').'
'.$physicalQuantity[$attribute['id_product_attribute']].''.$productDesignation[$attribute['id_product_attribute']].'
+
+
+ + + + + + +
+ '.$this->l('Available quantities for sale').' +
+
+ + + + '; + $return .= ' + + + + + + + + + + + + + + + +
+ depends_on_stock) ? 'checked="checked"' : '' ).' type="radio" name="depends_on_stock" class="depends_on_stock" id="depends_on_stock_1" value="1"/> + +

+
+ depends_on_stock) ? 'checked="checked"' : '' ).' type="radio" name="depends_on_stock" class="depends_on_stock" id="depends_on_stock_0" value="0"/> + +

+
+ + + + + + + + '; + foreach ($attributes as $attribute) + $return .= ' + + + + '; + $return .= ' + +
'.$this->l('Quantity').''.$this->l('Designation').'
+ '.$availableQuantity[$attribute['id_product_attribute']].' + + '.$productDesignation[$attribute['id_product_attribute']].'
+
+ + + + + + + +
'.$this->l('When out of stock:').' + out_of_stock == 0) ? 'checked="checked"' : '' ).' id="out_of_stock_1" type="radio" checked="checked" value="0" class="out_of_stock" name="out_of_stock"> + +
+ out_of_stock == 1) ? 'checked="checked"' : '' ).' id="out_of_stock_2" type="radio" value="1" class="out_of_stock" name="out_of_stock"> + +
+ out_of_stock == 2) ? 'checked="checked"' : '' ).' id="out_of_stock_3" type="radio" value="2" class="out_of_stock" name="out_of_stock"> + +
+
'; + $return .= ' +
+ '; + + return $return; + } + + public function ajaxProductQuantity($obj) + { + if(!Tools::getValue('action')) + return Tools::jsonEncode(array('error' => 'Undefined action')); + + switch(Tools::getValue('action')) + { + case 'depends_on_stock':elog((int)Tools::getValue('value')); + if (Tools::getValue('value') === false) + return Tools::jsonEncode(array('error' => 'Undefined value')); + if ((int)Tools::getValue('value') != 0 && (int)Tools::getValue('value') != 1) + return Tools::jsonEncode(array('error' => 'Uncorrect value')); + + StockAvailable::setProductDependsOnStock((int)Tools::getValue('value'), $obj->id); + break; + + case 'out_of_stock': + if (Tools::getValue('value') === false) + return Tools::jsonEncode(array('error' => 'Undefined value')); + if (!in_array((int)Tools::getValue('value'), array(0, 1, 2))) + return Tools::jsonEncode(array('error' => 'Uncorrect value')); + + StockAvailable::setProductOutOfStock((int)Tools::getValue('value'), $obj->id); + break; + + case 'set_qty': + if (Tools::getValue('value') === false) + return Tools::jsonEncode(array('error' => 'Undefined value')); + if (Tools::getValue('id_product_attribute') === false) + return Tools::jsonEncode(array('error' => 'Undefined id product attribute')); + $stock_available = new StockAvailable(StockAvailable::getIdStockAvailable($obj->id, (int)Tools::getValue('id_product_attribute'))); + $stock_available->quantity = (int)Tools::getValue('value'); + $stock_available->save(); + break; + } + + return Tools::jsonEncode(array('error' => false)); + } public function getLineTableImage($image, $imagesTotal, $token, $shops) { diff --git a/classes/Cart.php b/classes/Cart.php index 0f0ec4b77..dc88e08b4 100644 --- a/classes/Cart.php +++ b/classes/Cart.php @@ -373,7 +373,7 @@ class CartCore extends ObjectModel // Build SELECT $sql->select('cp.`id_product_attribute`, cp.`id_product`, cp.`quantity` AS cart_quantity, cp.id_shop, pl.`name`, p.`is_virtual`, pl.`description_short`, pl.`available_now`, pl.`available_later`, p.`id_product`, p.`id_category_default`, p.`id_supplier`, p.`id_manufacturer`, - p.`on_sale`, p.`ecotax`, p.`additional_shipping_cost`, p.`available_for_order`, p.`price`, p.`weight`, p.`width`, p.`height`, p.`depth`, p.`out_of_stock`, + p.`on_sale`, p.`ecotax`, p.`additional_shipping_cost`, p.`available_for_order`, p.`price`, p.`weight`, p.`width`, p.`height`, p.`depth`, sa.`out_of_stock`, p.`active`, p.`date_add`, p.`date_upd`, t.`id_tax`, tl.`name` AS tax, t.`rate`, stock.quantity, pl.`link_rewrite`, cl.`link_rewrite` AS category, CONCAT(cp.`id_product`, cp.`id_product_attribute`) AS unique_id'); @@ -388,6 +388,7 @@ class CartCore extends ObjectModel AND tr.`id_state` = 0 AND tr.`zipcode_from` = 0'); $sql->leftJoin('tax t ON t.`id_tax` = tr.`id_tax`'); + $sql->leftJoin('stock_available sa ON sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0'); $sql->leftJoin('tax_lang tl ON t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$this->id_lang); $sql->leftJoin('category_lang cl ON p.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.(int)$this->id_lang.Context::getContext()->shop->sqlLang('cl')); @@ -632,7 +633,7 @@ class CartCore extends ObjectModel { if ($operator == 'up') { - $sql = 'SELECT p.out_of_stock, stock.quantity + $sql = 'SELECT stock.out_of_stock, stock.quantity FROM '._DB_PREFIX_.'product p '.Product::sqlStock('p', $id_product_attribute, true, $shop).' WHERE p.id_product = '.$id_product; @@ -673,7 +674,7 @@ class CartCore extends ObjectModel /* Add product to the cart */ else { - $sql = 'SELECT p.out_of_stock, stock.quantity + $sql = 'SELECT stock.out_of_stock, stock.quantity FROM '._DB_PREFIX_.'product p '.Product::sqlStock('p', $id_product_attribute, true, $shop).' WHERE p.id_product = '.$id_product; diff --git a/classes/Category.php b/classes/Category.php index 587dc0f97..39f6aec5c 100644 --- a/classes/Category.php +++ b/classes/Category.php @@ -567,7 +567,7 @@ class CategoryCore extends ObjectModel return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); } - $sql = 'SELECT p.*, stock.quantity, pa.`id_product_attribute`, pl.`description`, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, m.`name` AS manufacturer_name, tl.`name` AS tax_name, t.`rate`, cl.`name` AS category_default, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new, + $sql = 'SELECT p.*, sa.out_of_stock, stock.quantity, pa.`id_product_attribute`, pl.`description`, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, m.`name` AS manufacturer_name, tl.`name` AS tax_name, t.`rate`, cl.`name` AS category_default, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new, (p.`price` * IF(t.`rate`,((100 + (t.`rate`))/100),1)) AS orderprice FROM `'._DB_PREFIX_.'category_product` cp LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product` @@ -581,10 +581,11 @@ class CategoryCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group` AND tr.`id_country` = '.(int)$context->country->id.' AND tr.`id_state` = 0 - AND tr.`zipcode_from` = 0) - LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) + AND tr.`zipcode_from` = 0) + LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$id_lang.') LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` + LEFT JOIN `'._DB_PREFIX_.'stock_available` sa ON sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0 WHERE cp.`id_category` = '.(int)($this->id) .($active ? ' AND p.`active` = 1' : '') .($id_supplier ? ' AND p.id_supplier = '.(int)$id_supplier : ''); diff --git a/classes/Manufacturer.php b/classes/Manufacturer.php index b9a6a88d3..bb74bf40f 100644 --- a/classes/Manufacturer.php +++ b/classes/Manufacturer.php @@ -277,7 +277,7 @@ class ManufacturerCore extends ObjectModel return (int)(sizeof($result)); } - $sql = 'SELECT p.*, pa.`id_product_attribute`, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, m.`name` AS manufacturer_name, tl.`name` AS tax_name, t.`rate`, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new, + $sql = 'SELECT p.*, sa.out_of_stock, pa.`id_product_attribute`, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, m.`name` AS manufacturer_name, tl.`name` AS tax_name, t.`rate`, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new, (p.`price` * ((100 + (t.`rate`))/100)) AS orderprice FROM `'._DB_PREFIX_.'product` p '.$context->shop->sqlAsso('product', 'p').' @@ -286,12 +286,13 @@ class ManufacturerCore extends ObjectModel LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product` AND i.`cover` = 1) LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.') LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group` - AND tr.`id_country` = '.(int)$context->country->id.' - AND tr.`id_state` = 0 - AND tr.`zipcode_from` = 0) - LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) + AND tr.`id_country` = '.(int)$context->country->id.' + AND tr.`id_state` = 0 + AND tr.`zipcode_from` = 0) + LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$id_lang.') - LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` + LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`) + LEFT JOIN `'._DB_PREFIX_.'stock_available` sa ON (sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0) WHERE p.`id_manufacturer` = '.(int)($id_manufacturer).($active ? ' AND p.`active` = 1' : '').' AND p.`id_product` IN ( SELECT cp.`id_product` diff --git a/classes/Product.php b/classes/Product.php index 952fcf43b..5973edff8 100644 --- a/classes/Product.php +++ b/classes/Product.php @@ -147,9 +147,6 @@ class ProductCore extends ObjectModel /** @var string Meta tag title */ public $meta_title; - /** @var integer Out of stock behavior */ - public $out_of_stock = 2; - /** @var boolean Product statuts */ public $quantity_discount = 0; @@ -239,7 +236,6 @@ class ProductCore extends ObjectModel 'height' => 'isUnsignedFloat', 'depth' => 'isUnsignedFloat', 'weight' => 'isUnsignedFloat', - 'out_of_stock' => 'isUnsignedInt', 'quantity_discount' => 'isBool', 'customizable' => 'isUnsignedInt', 'uploadable_files' => 'isUnsignedInt', @@ -274,7 +270,6 @@ class ProductCore extends ObjectModel 'id_manufacturer' => array('xlink_resource' => 'manufacturers'), 'id_supplier' => array('xlink_resource' => 'suppliers'), 'id_category_default' => array('xlink_resource' => 'categories'), - 'out_of_stock' => array('required' => true), 'new' => array(), 'cache_default_attribute' => array(), 'id_default_image' => array('getter' => 'getCoverWs', 'setter' => 'setCoverWs', 'xlink_resource' => array('resourceName' => 'images', 'subResourceName' => 'products')), @@ -340,6 +335,8 @@ class ProductCore extends ObjectModel * @FIXME */ $this->quantity = 0; + $this->out_of_stock = $this->getOutOfStock(); + $this->depends_on_stock = $this->getDependsOnStock(); if ($this->id_category_default) $this->category = Category::getLinkRewrite((int)$this->id_category_default, (int)$id_lang); @@ -373,7 +370,6 @@ class ProductCore extends ObjectModel $fields['height'] = (float)$this->height; $fields['depth'] = (float)$this->depth; $fields['weight'] = (float)$this->weight; - $fields['out_of_stock'] = pSQL($this->out_of_stock); $fields['quantity_discount'] = (int)$this->quantity_discount; $fields['customizable'] = (int)$this->customizable; $fields['uploadable_files'] = (int)$this->uploadable_files; @@ -1407,7 +1403,7 @@ class ProductCore extends ObjectModel } $sql = new DbQuery(); - $sql->select('p.*, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, p.`ean13`, p.`upc`, + $sql->select('p.*, sa.out_of_stock, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, p.`ean13`, p.`upc`, i.`id_image`, il.`legend`, t.`rate`, m.`name` AS manufacturer_name, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new, (p.`price` * ((100 + (t.`rate`))/100)) AS orderprice'); @@ -1420,6 +1416,7 @@ class ProductCore extends ObjectModel $sql->leftJoin('tax_rule tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group` AND tr.`id_country` = '.(int)$context->country->id.' AND tr.`id_state` = 0)'); $sql->leftJoin('tax t ON (t.`id_tax` = tr.`id_tax`)'); $sql->leftJoin('manufacturer m ON (m.`id_manufacturer` = p.`id_manufacturer`)'); + $sql->leftJoin('stock_available sa ON (sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0)'); $sql->where('p.`active` = 1'); $sql->where('DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0'); @@ -1500,7 +1497,7 @@ class ProductCore extends ObjectModel if (!$id_product) return false; - $sql = 'SELECT p.*, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, p.`ean13`, p.`upc`, + $sql = 'SELECT p.*, sa.out_of_stock, sa.out_of_stock out_of_stock, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, p.`ean13`, p.`upc`, i.`id_image`, il.`legend`, t.`rate` FROM `'._DB_PREFIX_.'product` p LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.$context->shop->sqlLang('pl').') @@ -1510,6 +1507,7 @@ class ProductCore extends ObjectModel AND tr.`id_country` = '.(int)Context::getContext()->country->id.' AND tr.`id_state` = 0) LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) + LEFT JOIN `'._DB_PREFIX_.'stock_available` sa ON sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0 WHERE p.id_product = '.(int)$id_product; $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql); @@ -1565,7 +1563,7 @@ class ProductCore extends ObjectModel return (int)($result['nb']); } - $sql = 'SELECT p.*, stock.quantity, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, + $sql = 'SELECT p.*, sa.out_of_stock, stock.quantity, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, t.`rate`, m.`name` AS manufacturer_name, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new FROM `'._DB_PREFIX_.'product` p @@ -1579,6 +1577,7 @@ class ProductCore extends ObjectModel AND tr.`id_state` = 0) LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`) + LEFT JOIN `'._DB_PREFIX_.'stock_available` sa ON (sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0) WHERE p.`active` = 1 AND p.`show_price` = 1 '.((!$beginning AND !$ending) ? ' AND p.`id_product` IN ('.((is_array($ids_product) AND count($ids_product)) ? implode(', ', $ids_product) : 0).')' : '').' @@ -2066,7 +2065,7 @@ class ProductCore extends ObjectModel { // @todo remove this code when query builder is accepted or removed $method = ($innerJoin) ? 'innerJoin' : 'leftJoin'; - $sql->$method('stock stock ON stock.id_product = '.pSQL($productAlias).'.id_product'); + $sql->$method('stock_available stock ON stock.id_product = '.pSQL($productAlias).'.id_product'); if (!is_null($productAttribute)) { if (!Combination::isFeatureActive()) @@ -2080,7 +2079,7 @@ class ProductCore extends ObjectModel } else { - $sql = (($innerJoin) ? ' INNER ' : ' LEFT ').'JOIN '._DB_PREFIX_.'stock stock ON stock.id_product = '.pSQL($productAlias).'.id_product'; + $sql = (($innerJoin) ? ' INNER ' : ' LEFT ').'JOIN '._DB_PREFIX_.'stock_available stock ON stock.id_product = '.pSQL($productAlias).'.id_product'; if (!is_null($productAttribute)) { if (!Combination::isFeatureActive()) @@ -2192,7 +2191,7 @@ class ProductCore extends ObjectModel if (!isset(self::$cacheStock[$this->id][$id_product_attribute])) { $sql = 'SELECT quantity - FROM '._DB_PREFIX_.'stock + FROM '._DB_PREFIX_.'stock_available WHERE id_product = '.$this->id.' AND id_product_attribute = '.(int)$id_product_attribute. $context->shop->sqlRestriction(Shop::SHARE_STOCK); @@ -2202,6 +2201,54 @@ class ProductCore extends ObjectModel return self::$cacheStock[$this->id][$id_product_attribute]; } + /** + * Get the value of "out of stock" of current product + * "ouf of stock" allow to order product without stock + * + * @since 1.5.0 + * @param Context $context + * @return int + */ + public function getOutOfStock(Context $context = null) + { + if (!$this->id) + return 0; + if (!$context) + $context = Context::getContext(); + + $id_shop = $context->shop->getID(true); + $sql = 'SELECT out_of_stock + FROM '._DB_PREFIX_.'stock_available + WHERE id_product = '.$this->id.' + AND id_product_attribute = 0'. + $context->shop->sqlRestriction(Shop::SHARE_STOCK); + return (int)Db::getInstance()->getValue($sql); + } + + /** + * Get the value of "depends on stock" of current product + * "depends on stock" allow managing quantity available manually + * + * @since 1.5.0 + * @param Context $context + * @return int + */ + public function getDependsOnStock(Context $context = null) + { + if (!$this->id) + return 0; + if (!$context) + $context = Context::getContext(); + + $id_shop = $context->shop->getID(true); + $sql = 'SELECT depends_on_stock + FROM '._DB_PREFIX_.'stock_available + WHERE id_product = '.$this->id.' + AND id_product_attribute = 0'. + $context->shop->sqlRestriction(Shop::SHARE_STOCK); + return (int)Db::getInstance()->getValue($sql); + } + /** * Update available product quantities * @@ -2255,9 +2302,9 @@ class ProductCore extends ObjectModel return true; } - public static function isAvailableWhenOutOfStock($oos) + public static function isAvailableWhenOutOfStock($out_of_stock) { - return !Configuration::get('PS_STOCK_MANAGEMENT') ? true : ((int)($oos) == 2 ? (int)(Configuration::get('PS_ORDER_OUT_OF_STOCK')) : (int)($oos)); + return !Configuration::get('PS_STOCK_MANAGEMENT') ? true : ((int)($out_of_stock) == 2 ? (int)(Configuration::get('PS_ORDER_OUT_OF_STOCK')) : (int)($out_of_stock)); } /** @@ -2386,7 +2433,7 @@ class ProductCore extends ObjectModel if (!$context) $context = Context::getContext(); - $sql = 'SELECT p.*, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, p.`ean13`, p.`upc`, + $sql = 'SELECT p.*, sa.out_of_stock, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, p.`ean13`, p.`upc`, i.`id_image`, il.`legend`, t.`rate`, m.`name` as manufacturer_name, cl.`name` AS category_default, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new FROM `'._DB_PREFIX_.'accessory` @@ -2401,6 +2448,7 @@ class ProductCore extends ObjectModel AND tr.`id_country` = '.(int)Context::getContext()->country->id.' AND tr.`id_state` = 0) LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) + LEFT JOIN `'._DB_PREFIX_.'stock_available` sa ON (sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0) WHERE `id_product_1` = '.(int)($this->id). ($active ? ' AND p.`active` = 1' : ''); if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql)) @@ -3633,5 +3681,20 @@ class ProductCore extends ObjectModel return isset($row['reference']); } + + /** + * Get all product attributes ids + * + * @since 1.5.0 + * @param int $id_product the id of the product + * @return array product attribute id list + */ + public static function getProductAttributesIds($id_product) + { + return Db::getInstance()->executeS(' + SELECT id_product_attribute + FROM `'._DB_PREFIX_.'product_attribute` + WHERE `id_product` = '.(int)$id_product); + } } diff --git a/classes/ProductSale.php b/classes/ProductSale.php index 97fe24847..8c17e08ca 100644 --- a/classes/ProductSale.php +++ b/classes/ProductSale.php @@ -78,7 +78,7 @@ class ProductSaleCore $groups = FrontController::getCurrentCustomerGroups(); $sqlGroups = (count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); - $sql = 'SELECT p.*, + $sql = 'SELECT p.*, sa.out_of_stock, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, m.`name` AS manufacturer_name, p.`id_manufacturer` as id_manufacturer, i.`id_image`, il.`legend`, ps.`quantity` AS sales, t.`rate`, pl.`meta_keywords`, pl.`meta_title`, pl.`meta_description`, @@ -91,9 +91,10 @@ class ProductSaleCore LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.') LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`) LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON p.`id_tax_rules_group` = tr.`id_tax_rules_group` - AND tr.`id_country` = '.(int)Context::getContext()->country->id.' - AND tr.`id_state` = 0 - LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) + AND tr.`id_country` = '.(int)Context::getContext()->country->id.' + AND tr.`id_state` = 0 + LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) + LEFT JOIN `'._DB_PREFIX_.'stock_available` sa ON (sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0) WHERE p.`active` = 1 AND p.`id_product` IN ( SELECT cp.`id_product` diff --git a/classes/Search.php b/classes/Search.php index 1c4832d1a..0bc378293 100644 --- a/classes/Search.php +++ b/classes/Search.php @@ -256,17 +256,18 @@ class SearchCore return $db->executeS($sql); } - $sql = 'SELECT p.*, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`name`, + $sql = 'SELECT p.*, sa.out_of_stock, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`name`, tax.`rate`, i.`id_image`, il.`legend`, m.`name` manufacturer_name '.$score.', DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 new FROM '._DB_PREFIX_.'product p INNER JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.$context->shop->sqlLang('pl').') LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group` - AND tr.`id_country` = '.(int)$context->country->id.' - AND tr.`id_state` = 0) - LEFT JOIN `'._DB_PREFIX_.'tax` tax ON (tax.`id_tax` = tr.`id_tax`) + AND tr.`id_country` = '.(int)$context->country->id.' + AND tr.`id_state` = 0) + LEFT JOIN `'._DB_PREFIX_.'tax` tax ON (tax.`id_tax` = tr.`id_tax`) LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product` AND i.`cover` = 1) LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.') + LEFT JOIN `'._DB_PREFIX_.'stock_available` sa ON (sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0) WHERE p.`id_product` '.$productPool.' '.($orderBy ? 'ORDER BY '.$orderBy : '').($orderWay ? ' '.$orderWay : '').' LIMIT '.(int)(($pageNumber - 1) * $pageSize).','.(int)$pageSize; @@ -276,9 +277,9 @@ class SearchCore FROM '._DB_PREFIX_.'product p INNER JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.$context->shop->sqlLang('pl').') LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group` - AND tr.`id_country` = '.(int)Context::getContext()->country->id.' - AND tr.`id_state` = 0) - LEFT JOIN `'._DB_PREFIX_.'tax` tax ON (tax.`id_tax` = tr.`id_tax`) + AND tr.`id_country` = '.(int)Context::getContext()->country->id.' + AND tr.`id_state` = 0) + LEFT JOIN `'._DB_PREFIX_.'tax` tax ON (tax.`id_tax` = tr.`id_tax`) LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product` AND i.`cover` = 1) LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.') @@ -564,7 +565,7 @@ class SearchCore return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); } - $sql = 'SELECT DISTINCT p.*, pl.`description_short`, pl.`link_rewrite`, pl.`name`, tax.`rate`, i.`id_image`, il.`legend`, m.`name` manufacturer_name, 1 position, + $sql = 'SELECT DISTINCT p.*, sa.out_of_stock, pl.`description_short`, pl.`link_rewrite`, pl.`name`, tax.`rate`, i.`id_image`, il.`legend`, m.`name` manufacturer_name, 1 position, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 new FROM `'._DB_PREFIX_.'product` p INNER JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.$context->shop->sqlLang('pl').') @@ -574,12 +575,13 @@ class SearchCore LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group` AND tr.`id_country` = '.(int)$context->country->id.' AND tr.`id_state` = 0) - LEFT JOIN `'._DB_PREFIX_.'tax` tax ON (tax.`id_tax` = tr.`id_tax`) + LEFT JOIN `'._DB_PREFIX_.'tax` tax ON (tax.`id_tax` = tr.`id_tax`) LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON (m.`id_manufacturer` = p.`id_manufacturer`) LEFT JOIN `'._DB_PREFIX_.'product_tag` pt ON (p.`id_product` = pt.`id_product`) LEFT JOIN `'._DB_PREFIX_.'tag` t ON (pt.`id_tag` = t.`id_tag` AND t.`id_lang` = '.(int)$id_lang.') LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_product` = p.`id_product`) LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = cp.`id_category`) + LEFT JOIN `'._DB_PREFIX_.'stock_available` sa ON (sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0) WHERE p.`active` = 1 AND cg.`id_group` '.(!$id_customer ? '= 1' : 'IN ( SELECT id_group FROM '._DB_PREFIX_.'customer_group diff --git a/classes/Supplier.php b/classes/Supplier.php index ac4d3fe6a..7d397c258 100644 --- a/classes/Supplier.php +++ b/classes/Supplier.php @@ -214,7 +214,7 @@ class SupplierCore extends ObjectModel return (int)(sizeof($result)); } - $sql = 'SELECT p.*, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, s.`name` AS supplier_name, tl.`name` AS tax_name, t.`rate`, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new, + $sql = 'SELECT p.*, sa.out_of_stock, pl.`description`, pl.`description_short`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, i.`id_image`, il.`legend`, s.`name` AS supplier_name, tl.`name` AS tax_name, t.`rate`, DATEDIFF(p.`date_add`, DATE_SUB(NOW(), INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY)) > 0 AS new, (p.`price` * ((100 + (t.`rate`))/100)) AS orderprice, m.`name` AS manufacturer_name FROM `'._DB_PREFIX_.'product` p LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Context::getContext()->shop->sqlLang('pl').') @@ -224,10 +224,11 @@ class SupplierCore extends ObjectModel AND tr.`id_country` = '.(int)Context::getContext()->country->id.' AND tr.`id_state` = 0 AND tr.`zipcode_from` = 0) - LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) + LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`) LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$id_lang.') LEFT JOIN `'._DB_PREFIX_.'supplier` s ON s.`id_supplier` = p.`id_supplier` LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` + LEFT JOIN `'._DB_PREFIX_.'stock_available` sa ON (sa.`id_product` = p.`id_product` AND sa.id_product_attribute = 0) WHERE p.`id_supplier` = '.(int)$id_supplier.($active ? ' AND p.`active` = 1' : '').' AND p.`id_product` IN ( SELECT cp.`id_product` diff --git a/classes/stock/StockAvailable.php b/classes/stock/StockAvailable.php index 9fc62a523..06a60ee75 100644 --- a/classes/stock/StockAvailable.php +++ b/classes/stock/StockAvailable.php @@ -60,8 +60,8 @@ class StockAvailableCore extends ObjectModel 'id_product_attribute' => 'isUnsignedId', 'id_shop' => 'isUnsignedId', 'quantity' => 'isInt', - 'depends_on_stocks' => 'isBool', - 'out_of_stock' => 'isBool' + 'depends_on_stock' => 'isBool', + 'out_of_stock' => 'isInt' ); protected $table = 'stock_available'; @@ -74,7 +74,7 @@ class StockAvailableCore extends ObjectModel $fields['id_product_attribute'] = (int)$this->id_product_attribute; $fields['id_shop'] = (int)$this->id_shop; $fields['quantity'] = (int)$this->quantity; - $fields['depends_on_stocks'] = (bool)$this->depends_on_stocks; + $fields['depends_on_stock'] = (bool)$this->depends_on_stock; $fields['out_of_stock'] = (bool)$this->out_of_stock; return $fields; } @@ -87,8 +87,11 @@ class StockAvailableCore extends ObjectModel * @param int $id_shop * @return int */ - public static function getIdStockAvailable($id_product, $id_product_attribute = null, $id_shop) + public static function getIdStockAvailable($id_product, $id_product_attribute = null, $id_shop = null) { + if (is_null($id_shop)) + $id_shop = Context::getContext()->shop->getID(true); + $query = new DbQuery(); $query->select('id_stock_available'); $query->from('stock_available'); @@ -163,4 +166,97 @@ class StockAvailableCore extends ObjectModel Db::getInstance()->autoExecute($query['table'], $query['data'], $query['type'], $query['where']); } } + + /** + * For a given id_product, sets if stock available depends on stock + * + * @param int $depends_on_stock + * @param int $id_product + * @param int $id_shop + */ + public static function setProductDependsOnStock($depends_on_stock, $id_product, $id_shop = null) + { + if (is_null($id_shop)) + $id_shop = Context::getContext()->shop->getID(true); + + Db::getInstance()->autoExecute( + 'stock_available', + array('depends_on_stock' => (boolean)$depends_on_stock), + 'UPDATE', + 'id_product = '.(int)$id_product.' AND id_shop = '.(int)$id_shop + ); + if($depends_on_stock) + StockAvailable::synchronize($id_product); + } + + /** + * For a given id_product, sets if product is available out of stocks + * + * @param int $out_of_stock + * @param int $id_product + * @param int $id_shop + */ + public static function setProductOutOfStock($out_of_stock, $id_product, $id_shop = null) + { + if (is_null($id_shop)) + $id_shop = Context::getContext()->shop->getID(true); + + Db::getInstance()->autoExecute( + 'stock_available', + array('out_of_stock' => (int)$out_of_stock), + 'UPDATE', + 'id_product = '.(int)$id_product.' AND id_shop = '.(int)$id_shop + ); + } + + /** + * For a given id_product and id_product_attribute, gets stock available + * + * @param int $id_product + * @param int $id_product_attribute + * @param int $id_shop + */ + public static function getStockAvailableForProduct($id_product, $id_product_attribute = null, $id_shop = null) + { + if (is_null($id_shop)) + $id_shop = Context::getContext()->shop->getID(true); + + $query = new DbQuery(); + $query->select('quantity'); + $query->from('stock_available'); + $query->where('id_product = '.(int)$id_product); + $query->where('id_product_attribute = '.(int)$id_product_attribute); + $query->where('id_shop = '.(int)$id_shop); + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); + } + + /** + * After saving a quantity available, upgrade the total_quantity_available + */ + public function save($nullValues = false, $autodate = true) + { + if (!parent::save($nullValues, $autodate)) + return false; + + if ($this->id_product_attribute = 0) + return true; + + $id_stock_available = StockAvailable::getIdStockAvailable($this->id_product, 0, $this->id_shop); + + $total_quantity = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT sum(quantity) FROM '._DB_PREFIX_.'stock_available + WHERE id_product = '.(int)$this->id_product.' AND id_shop = '.(int)$this->id_shop.' AND id_product_attribute <> 0'); + + if (!$id_stock_available) + { + return (int)Db::getInstance()->execute('INSERT '._DB_PREFIX_.'stock_available + SET id_product = '.(int)$this->id_product.', id_product_attribute = 0, id_shop = '.(int)$this->id_shop.' + quantity = '.(int)$total_quantity); + } + else + { + return (int)Db::getInstance()->execute('UPDATE '._DB_PREFIX_.'stock_available + SET quantity = '.(int)$total_quantity.' + WHERE id_stock_available = '.(int)$id_stock_available); + } + } } \ No newline at end of file diff --git a/classes/stock/StockManager.php b/classes/stock/StockManager.php index 7c3b6ffbb..94067eb12 100644 --- a/classes/stock/StockManager.php +++ b/classes/stock/StockManager.php @@ -32,9 +32,9 @@ class StockManagerCore implements StockManagerInterface { - /** - * @see StockManagerInterface::isAvailable() - */ + /** + * @see StockManagerInterface::isAvailable() + */ public static function isAvailable() { // Default Manager : always available diff --git a/modules/mailalerts/mailalerts.php b/modules/mailalerts/mailalerts.php index fe53c1a1d..d663bda14 100644 --- a/modules/mailalerts/mailalerts.php +++ b/modules/mailalerts/mailalerts.php @@ -325,7 +325,7 @@ class MailAlerts extends Module public function hookUpdateProductAttribute($params) { $sql = 'SELECT id_product, quantity - FROM '._DB_PREFIX_.'stock + FROM '._DB_PREFIX_.'stock_available WHERE id_product_attribute = '.(int)$params['id_product_attribute'] .Context::getContext()->shop->sqlRestriction(Shop::SHARE_STOCK); $result = Db::getInstance()->getRow($sql);