// Update Stats interface relative to stock available functionnality + retrocompatibility for supplier reference and wholesale_price for a product/product attribute

This commit is contained in:
dSevere
2011-12-06 14:02:50 +00:00
parent 575a3eb00c
commit 7d88ddef77
5 changed files with 64 additions and 40 deletions
+30 -6
View File
@@ -2044,6 +2044,8 @@ class AdminProductsControllerCore extends AdminController
{ {
if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product')))) if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product'))))
{ {
$update_product = false;
// Get all available suppliers // Get all available suppliers
$suppliers = Supplier::getSuppliers(); $suppliers = Supplier::getSuppliers();
@@ -2089,6 +2091,13 @@ class AdminProductsControllerCore extends AdminController
} }
} }
// Manage defaut supplier for product
if ($new_default_supplier != 0 && $new_default_supplier != $product->id_supplier && Supplier::supplierExists($new_default_supplier))
{
$product->id_supplier = $new_default_supplier;
$update_product = true;
}
$this->confirmations[] = $this->l('Suppliers of the product have been updated'); $this->confirmations[] = $this->l('Suppliers of the product have been updated');
// Get all id_product_attribute // Get all id_product_attribute
@@ -2169,17 +2178,32 @@ class AdminProductsControllerCore extends AdminController
} }
} }
// Retro-compatibility code
if ($product->id_supplier == $supplier->id_supplier) if ($product->id_supplier == $supplier->id_supplier)
$product->wholesale_price = Tools::convertPrice($price, $id_currency); {
if ((int)$attribute['id_product_attribute'] > 0)
{
Db::getInstance()->execute('
UPDATE '._DB_PREFIX_.'product_attribute
SET supplier_reference = '.$reference.',
wholesale_price = '.Tools::convertPrice($price, $id_currency).'
WHERE id_product = '.(int)$product->id.'
AND id_product_attribute = '.(int)$attribute['id_product_attribute'].'
LIMIT 1
');
}
else
{
$product->wholesale_price = Tools::convertPrice($price, $id_currency); //converted in the default currency
$product->supplier_reference = $reference;
$update_product = true;
}
}
} }
} }
// Manage defaut supplier for product if ($update_product)
if ($new_default_supplier != 0 && $new_default_supplier != $product->id_supplier && Supplier::supplierExists($new_default_supplier))
{
$product->id_supplier = $new_default_supplier;
$product->update(); $product->update();
}
$this->confirmations[] = $this->l('Supplier Reference(s) of the product have been updated'); $this->confirmations[] = $this->l('Supplier Reference(s) of the product have been updated');
} }
@@ -1,6 +1,6 @@
<?php <?php
/* /*
* 2007-2011 PrestaShop * 2007-2011 PrestaShop
* *
* NOTICE OF LICENSE * NOTICE OF LICENSE
* *
@@ -103,9 +103,9 @@ class StatsBestProducts extends ModuleGrid
), ),
array( array(
'id' => 'quantity', 'id' => 'quantity',
'header' => $this->l('Stock'), 'header' => $this->l('Available Quantity for sale'),
'dataIndex' => 'quantity', 'dataIndex' => 'quantity',
'width' => 50, 'width' => 150,
'align' => 'right' 'align' => 'right'
) )
); );
@@ -149,8 +149,9 @@ class StatsBestProducts extends ModuleGrid
$dateBetween = $this->getDate(); $dateBetween = $this->getDate();
$arrayDateBetween = explode(' AND ', $dateBetween); $arrayDateBetween = explode(' AND ', $dateBetween);
$this->_query = 'SELECT SQL_CALC_FOUND_ROWS p.reference, p.id_product, pl.name, ROUND(AVG(od.product_price / o.conversion_rate), 2) as avgPriceSold, $this->_query = 'SELECT SQL_CALC_FOUND_ROWS p.reference, p.id_product, pl.name,
IFNULL((SELECT SUM(pa.quantity) FROM '._DB_PREFIX_.'product_attribute pa WHERE pa.id_product = p.id_product GROUP BY pa.id_product), p.quantity) as quantity, ROUND(AVG(od.product_price / o.conversion_rate), 2) as avgPriceSold,
IFNULL(stock.quantity, 0) as quantity,
IFNULL(SUM(od.product_quantity), 0) AS totalQuantitySold, IFNULL(SUM(od.product_quantity), 0) AS totalQuantitySold,
ROUND(IFNULL(IFNULL(SUM(od.product_quantity), 0) / (1 + LEAST(TO_DAYS('.$arrayDateBetween[1].'), TO_DAYS(NOW())) - GREATEST(TO_DAYS('.$arrayDateBetween[0].'), TO_DAYS(p.date_add))), 0), 2) as averageQuantitySold, ROUND(IFNULL(IFNULL(SUM(od.product_quantity), 0) / (1 + LEAST(TO_DAYS('.$arrayDateBetween[1].'), TO_DAYS(NOW())) - GREATEST(TO_DAYS('.$arrayDateBetween[0].'), TO_DAYS(p.date_add))), 0), 2) as averageQuantitySold,
ROUND(IFNULL(SUM((od.product_price * od.product_quantity) / o.conversion_rate), 0), 2) AS totalPriceSold, ROUND(IFNULL(SUM((od.product_price * od.product_quantity) / o.conversion_rate), 0), 2) AS totalPriceSold,
@@ -168,6 +169,7 @@ class StatsBestProducts extends ModuleGrid
LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (p.id_product = pl.id_product AND pl.id_lang = '.(int)$this->getLang().$this->context->shop->addSqlRestrictionOnLang('pl').') LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (p.id_product = pl.id_product AND pl.id_lang = '.(int)$this->getLang().$this->context->shop->addSqlRestrictionOnLang('pl').')
LEFT JOIN '._DB_PREFIX_.'order_detail od ON od.product_id = p.id_product LEFT JOIN '._DB_PREFIX_.'order_detail od ON od.product_id = p.id_product
LEFT JOIN '._DB_PREFIX_.'orders o ON od.id_order = o.id_order LEFT JOIN '._DB_PREFIX_.'orders o ON od.id_order = o.id_order
'.Product::sqlStock('p', 0).'
WHERE p.active = 1 WHERE p.active = 1
AND o.valid = 1 AND o.valid = 1
AND o.invoice_date BETWEEN '.$dateBetween.' AND o.invoice_date BETWEEN '.$dateBetween.'
+8 -10
View File
@@ -110,7 +110,7 @@ class StatsCheckUp extends Module
1 => '<img src="../modules/'.$this->name.'/orange.png" alt="'.$this->l('average').'" />', 1 => '<img src="../modules/'.$this->name.'/orange.png" alt="'.$this->l('average').'" />',
2 => '<img src="../modules/'.$this->name.'/green.png" alt="'.$this->l('good').'" />' 2 => '<img src="../modules/'.$this->name.'/green.png" alt="'.$this->l('good').'" />'
); );
$tokenProducts = Tools::getAdminToken('AdminCatalog'.(int)(Tab::getIdFromClassName('AdminCatalog')).(int)Context::getContext()->employee->id); $tokenProducts = Tools::getAdminToken('AdminProducts'.(int)(Tab::getIdFromClassName('AdminProducts')).(int)Context::getContext()->employee->id);
$divisor = 4; $divisor = 4;
$totals = array('products' => 0, 'active' => 0, 'images' => 0, 'sales' => 0, 'stock' => 0); $totals = array('products' => 0, 'active' => 0, 'images' => 0, 'sales' => 0, 'stock' => 0);
foreach ($languages as $language) foreach ($languages as $language)
@@ -138,12 +138,10 @@ class StatsCheckUp extends Module
WHERE od.product_id = p.id_product WHERE od.product_id = p.id_product
AND o.invoice_date BETWEEN '.ModuleGraph::getDateBetween().' AND o.invoice_date BETWEEN '.ModuleGraph::getDateBetween().'
'.$this->sqlShopRestriction(Shop::SHARE_ORDER, 'o').' '.$this->sqlShopRestriction(Shop::SHARE_ORDER, 'o').'
) as nbSales, IFNULL(( ) as nbSales,
SELECT SUM(pa.quantity) IFNULL(stock.quantity, 0) as stock
FROM '._DB_PREFIX_.'product_attribute pa
WHERE pa.id_product = p.id_product
), p.quantity) as stock
FROM '._DB_PREFIX_.'product p FROM '._DB_PREFIX_.'product p
'.Product::sqlStock('p', 0).'
LEFT JOIN '._DB_PREFIX_.'product_lang pl LEFT JOIN '._DB_PREFIX_.'product_lang pl
ON (p.id_product = pl.id_product AND pl.id_lang = '.(int)$this->context->language->id.$this->context->shop->addSqlRestrictionOnLang('pl').') ON (p.id_product = pl.id_product AND pl.id_lang = '.(int)$this->context->language->id.$this->context->shop->addSqlRestrictionOnLang('pl').')
'.$this->context->shop->addSqlAssociation('product', 'p').' '.$this->context->shop->addSqlAssociation('product', 'p').'
@@ -157,7 +155,7 @@ class StatsCheckUp extends Module
'DESCRIPTIONS' => array('name' => $this->l('Descriptions'), 'text' => $this->l('chars (without HTML)')), 'DESCRIPTIONS' => array('name' => $this->l('Descriptions'), 'text' => $this->l('chars (without HTML)')),
'IMAGES' => array('name' => $this->l('Images'), 'text' => $this->l('images')), 'IMAGES' => array('name' => $this->l('Images'), 'text' => $this->l('images')),
'SALES' => array('name' => $this->l('Sales'), 'text' => $this->l('orders / month')), 'SALES' => array('name' => $this->l('Sales'), 'text' => $this->l('orders / month')),
'STOCK' => array('name' => $this->l('Stock'), 'text' => $this->l('items')) 'STOCK' => array('name' => $this->l('Available quantities for sale'), 'text' => $this->l('items'))
); );
$this->html = ' $this->html = '
@@ -213,7 +211,7 @@ class StatsCheckUp extends Module
$this->html .= ' $this->html .= '
<th>'.$this->l('Images').'</th> <th>'.$this->l('Images').'</th>
<th>'.$this->l('Sales').'</th> <th>'.$this->l('Sales').'</th>
<th>'.$this->l('Stock').'</th> <th>'.$this->l('Available quantities for sale').'</th>
<th>'.$this->l('Global').'</th> <th>'.$this->l('Global').'</th>
</tr>'; </tr>';
foreach ($result as $row) foreach ($result as $row)
@@ -246,7 +244,7 @@ class StatsCheckUp extends Module
$this->html .= '<tr> $this->html .= '<tr>
<td>'.$row['id_product'].'</td> <td>'.$row['id_product'].'</td>
<td style="text-align:left"><a href="index.php?tab=AdminCatalog&updateproduct&id_product='.$row['id_product'].'&token='.$tokenProducts.'">'.Tools::substr($row['name'], 0, 42).'</a></td> <td style="text-align:left"><a href="index.php?tab=AdminProducts&updateproduct&id_product='.$row['id_product'].'&token='.$tokenProducts.'">'.Tools::substr($row['name'], 0, 42).'</a></td>
<td>'.$arrayColors[$scores['active']].'</td>'; <td>'.$arrayColors[$scores['active']].'</td>';
foreach ($languages as $language) foreach ($languages as $language)
if (isset($row['desclength_'.$language['iso_code']])) if (isset($row['desclength_'.$language['iso_code']]))
@@ -286,7 +284,7 @@ class StatsCheckUp extends Module
$this->html .= ' $this->html .= '
<th>'.$this->l('Images').'</th> <th>'.$this->l('Images').'</th>
<th>'.$this->l('Sales').'</th> <th>'.$this->l('Sales').'</th>
<th>'.$this->l('Stock').'</th> <th>'.$this->l('Available quantities for sale').'</th>
<th>'.$this->l('Global').'</th> <th>'.$this->l('Global').'</th>
</tr> </tr>
<tr> <tr>
+5 -4
View File
@@ -99,15 +99,16 @@ class StatsProduct extends ModuleGraph
private function getProducts($id_lang) private function getProducts($id_lang)
{ {
$sql = 'SELECT p.`id_product`, p.reference, pl.`name`, IFNULL( $sql = 'SELECT p.`id_product`, p.reference, pl.`name`, IFNULL(stock.quantity, 0) as quantity
(SELECT SUM(pa.quantity) FROM '._DB_PREFIX_.'product_attribute pa WHERE pa.id_product = p.id_product), p.quantity) as quantity
FROM `'._DB_PREFIX_.'product` p FROM `'._DB_PREFIX_.'product` p
'.Product::sqlStock('p', 0).'
LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON p.`id_product` = pl.`id_product`'.$this->context->shop->addSqlRestrictionOnLang('pl').' LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON p.`id_product` = pl.`id_product`'.$this->context->shop->addSqlRestrictionOnLang('pl').'
'.$this->context->shop->addSqlAssociation('product', 'p').' '.$this->context->shop->addSqlAssociation('product', 'p').'
'.(Tools::getValue('id_category') ? 'LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON p.`id_product` = cp.`id_product`' : '').' '.(Tools::getValue('id_category') ? 'LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON p.`id_product` = cp.`id_product`' : '').'
WHERE pl.`id_lang` = '.(int)$id_lang.' WHERE pl.`id_lang` = '.(int)$id_lang.'
'.(Tools::getValue('id_category') ? 'AND cp.id_category = '.(int)Tools::getValue('id_category') : '').' '.(Tools::getValue('id_category') ? 'AND cp.id_category = '.(int)Tools::getValue('id_category') : '').'
ORDER BY pl.`name`'; ORDER BY pl.`name`';
return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
} }
@@ -258,7 +259,7 @@ class StatsProduct extends ModuleGraph
<tr> <tr>
<th>'.$this->l('Ref.').'</th> <th>'.$this->l('Ref.').'</th>
<th>'.$this->l('Name').'</th> <th>'.$this->l('Name').'</th>
<th>'.$this->l('Stock').'</th> <th>'.$this->l('Available Quantity for sale').'</th>
</tr> </tr>
</thead><tbody>'; </thead><tbody>';
@@ -283,7 +284,7 @@ class StatsProduct extends ModuleGraph
'.$this->l('After choosing a category and selecting a product, informational graphs will appear. Then, you will be able to analyze them.').' '.$this->l('After choosing a category and selecting a product, informational graphs will appear. Then, you will be able to analyze them.').'
<ul> <ul>
<li class="bullet">'.$this->l('If you notice that a product is successful and often purchased, but viewed infrequently, you should put it more prominently on your webshop front-office.').'</li> <li class="bullet">'.$this->l('If you notice that a product is successful and often purchased, but viewed infrequently, you should put it more prominently on your webshop front-office.').'</li>
<li class="bullet">'.$this->l('On the other hand, if a product has many viewings but is not often purchased, <li class="bullet">'.$this->l('On the other hand, if a product has many viewings but is not often purchased,
we advise you to check or modify this product\'s information, description and photography again.').' we advise you to check or modify this product\'s information, description and photography again.').'
</li> </li>
</ul> </ul>
+14 -15
View File
@@ -1,6 +1,6 @@
<?php <?php
/* /*
* 2007-2011 PrestaShop * 2007-2011 PrestaShop
* *
* NOTICE OF LICENSE * NOTICE OF LICENSE
* *
@@ -24,7 +24,7 @@
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
* International Registered Trademark & Property of PrestaShop SA * International Registered Trademark & Property of PrestaShop SA
*/ */
if (!defined('_PS_VERSION_')) if (!defined('_PS_VERSION_'))
exit; exit;
@@ -42,7 +42,7 @@ class StatsStock extends Module
parent::__construct(); parent::__construct();
$this->displayName = $this->l('Stock stats'); $this->displayName = $this->l('Available quantities stats');
$this->description = ''; $this->description = '';
} }
@@ -66,25 +66,24 @@ class StatsStock extends Module
FROM '._DB_PREFIX_.'product_attribute pa WHERE p.id_product = pa.id_product FROM '._DB_PREFIX_.'product_attribute pa WHERE p.id_product = pa.id_product
AND wholesale_price != 0 AND wholesale_price != 0
), p.wholesale_price) as wholesale_price, ), p.wholesale_price) as wholesale_price,
IFNULL(( IFNULL(stock.quantity, 0) as quantity
SELECT SUM(pa.quantity)
FROM '._DB_PREFIX_.'product_attribute pa WHERE p.id_product = pa.id_product
), p.quantity) as quantity,
IFNULL((
SELECT SUM(IF(pa.wholesale_price > 0, pa.wholesale_price, p.wholesale_price) * pa.quantity)
FROM '._DB_PREFIX_.'product_attribute pa WHERE p.id_product = pa.id_product
), p.wholesale_price * p.quantity) as stockvalue
FROM '._DB_PREFIX_.'product p FROM '._DB_PREFIX_.'product p
'.$this->context->shop->addSqlAssociation('product', 'p').' '.$this->context->shop->addSqlAssociation('product', 'p').'
INNER JOIN '._DB_PREFIX_.'product_lang pl INNER JOIN '._DB_PREFIX_.'product_lang pl
ON (p.id_product = pl.id_product AND pl.id_lang = '.(int)$this->context->language->id.$this->context->shop->addSqlRestrictionOnLang('pl').') ON (p.id_product = pl.id_product AND pl.id_lang = '.(int)$this->context->language->id.$this->context->shop->addSqlRestrictionOnLang('pl').')
'.Product::sqlStock('p', 0).'
WHERE 1 = 1 WHERE 1 = 1
'.$filter; '.$filter;
$products = Db::getInstance()->executeS($sql); $products = Db::getInstance()->executeS($sql);
foreach ($products as $key => $p)
{
$products[$key]['stockvalue'] = $p['wholesale_price'] * $p['quantity'];
}
$this->html .= ' $this->html .= '
<script type="text/javascript">$(\'#calendar\').slideToggle();</script> <script type="text/javascript">$(\'#calendar\').slideToggle();</script>
<div class="blocStats"><h2 class="icon-'.$this->name.'"><span></span>'.$this->l('Stock value').'</h2> <div class="blocStats"><h2 class="icon-'.$this->name.'"><span></span>'.$this->l('Available quantities for sale valuation').'</h2>
<form action="'.$ru.'" method="post"> <form action="'.$ru.'" method="post">
<input type="hidden" name="submitCategory" value="1" /> <input type="hidden" name="submitCategory" value="1" />
'.$this->l('Category').' : <select name="statsstock_id_category" onchange="this.form.submit();"> '.$this->l('Category').' : <select name="statsstock_id_category" onchange="this.form.submit();">
@@ -107,7 +106,7 @@ class StatsStock extends Module
<th>'.$this->l('ID').'</th> <th>'.$this->l('ID').'</th>
<th>'.$this->l('Ref.').'</th> <th>'.$this->l('Ref.').'</th>
<th style="width:350px">'.$this->l('Item').'</th> <th style="width:350px">'.$this->l('Item').'</th>
<th>'.$this->l('Stock').'</th> <th>'.$this->l('Available quantity for sale').'</th>
<th>'.$this->l('Price*').'</th> <th>'.$this->l('Price*').'</th>
<th>'.$this->l('Value').'</th> <th>'.$this->l('Value').'</th>
</tr>'; </tr>';
@@ -128,7 +127,7 @@ class StatsStock extends Module
$this->html .= ' $this->html .= '
<tr> <tr>
<th colspan="3"></th> <th colspan="3"></th>
<th>'.$this->l('Total stock').'</th> <th>'.$this->l('Total quantities').'</th>
<th>'.$this->l('Avg price').'</th> <th>'.$this->l('Avg price').'</th>
<th>'.$this->l('Total value').'</th> <th>'.$this->l('Total value').'</th>
</tr> </tr>
@@ -139,7 +138,7 @@ class StatsStock extends Module
<td>'.Tools::displayPrice($rollup['stockvalue'], $currency).'</td> <td>'.Tools::displayPrice($rollup['stockvalue'], $currency).'</td>
</tr> </tr>
</table> </table>
<p>* '.$this->l('Average price when the product has attributes.').'</p></div>'; <p>* '.$this->l('Correspond to the default wholesale price according to the default supplier for the product. An average price is used when the product has attributes.').'</p></div>';
return $this->html; return $this->html;
} }