From 1a8884bbbee037f128875d5d138a98571b0be2f9 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur <eldy@destailleur.fr>
Date: Mon, 22 May 2017 15:20:52 +0200
Subject: [PATCH] NEW Can filter on year and product tags on the product
 statistic page

---
 htdocs/categories/class/categorie.class.php   |  26 +-
 htdocs/core/class/html.form.class.php         |   2 +-
 htdocs/langs/en_US/other.lang                 |  24 +-
 htdocs/product/ajax/products.php              |   4 +-
 htdocs/product/card.php                       |   3 +-
 htdocs/product/class/product.class.php        |  57 +-
 htdocs/product/composition/card.php           |  83 ++-
 htdocs/product/list.php                       |  68 +-
 htdocs/product/stats/card.php                 | 601 ++++++++++--------
 htdocs/product/stats/commande.php             |   2 +-
 htdocs/product/stats/commande_fournisseur.php |   2 +-
 htdocs/product/stats/contrat.php              |   2 +-
 htdocs/product/stats/facture.php              |   2 +-
 htdocs/product/stats/facture_fournisseur.php  |   2 +-
 htdocs/product/stats/propal.php               |   2 +-
 15 files changed, 486 insertions(+), 394 deletions(-)

diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php
index 518c3faa683..142cc22fe75 100644
--- a/htdocs/categories/class/categorie.class.php
+++ b/htdocs/categories/class/categorie.class.php
@@ -792,11 +792,12 @@ class Categorie extends CommonObject
 	/**
 	 * Return list of fetched instance of elements having this category
 	 *
-	 * @param   string $type Type of category ('customer', 'supplier', 'contact', 'product', 'member')
-	 *
-	 * @return  mixed        -1 if KO, array of instance of object if OK
+	 * @param   string     $type       Type of category ('customer', 'supplier', 'contact', 'product', 'member')
+	 * @param   int        $onlyids    Return only ids of objects (consume less memory)
+	 * @return  mixed                  -1 if KO, array of instance of object if OK
+	 * @see containsObject
 	 */
-	function getObjectsInCateg($type)
+	function getObjectsInCateg($type, $onlyids=0)
 	{
 		$objs = array();
 
@@ -813,10 +814,18 @@ class Categorie extends CommonObject
 		$resql = $this->db->query($sql);
 		if ($resql)
 		{
-			while ($rec = $this->db->fetch_array($resql)) {
-				$obj = new $this->MAP_OBJ_CLASS[$type]( $this->db );
-				$obj->fetch( $rec['fk_' . $this->MAP_CAT_FK[$type]]);
-				$objs[] = $obj;
+			while ($rec = $this->db->fetch_array($resql)) 
+			{
+			    if ($onlyids)
+			    {
+			        $objs[] = $rec['fk_' . $this->MAP_CAT_FK[$type]];
+			    }
+			    else
+			    {
+				    $obj = new $this->MAP_OBJ_CLASS[$type]( $this->db );
+				    $obj->fetch( $rec['fk_' . $this->MAP_CAT_FK[$type]]);
+				    $objs[] = $obj;
+			    }
 			}
 			return $objs;
 		}
@@ -834,6 +843,7 @@ class Categorie extends CommonObject
 	 * @param   int    $object_id id of the object to search
 	 *
 	 * @return  int                        number of occurrences
+	 * @see getObjectsInCateg
 	 */
 	function containsObject($type, $object_id )
 	{
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index f58e96087b8..561504f7845 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -4783,7 +4783,7 @@ class Form
                 {
                     $retstring.='<select'.($disabled?' disabled':'').' class="flat valignmiddle maxwidth75imp" id="'.$prefix.'year" name="'.$prefix.'year">';
 
-                    for ($year = $syear - 5; $year < $syear + 10 ; $year++)
+                    for ($year = $syear - 10; $year < $syear + 10 ; $year++)
                     {
                         $retstring.='<option value="'.$year.'"'.($year == $syear ? ' selected':'').'>'.$year.'</option>';
                     }
diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang
index 11a09af3373..02fa209c340 100644
--- a/htdocs/langs/en_US/other.lang
+++ b/htdocs/langs/en_US/other.lang
@@ -160,18 +160,18 @@ ProfIdShortDesc=<b>Prof Id %s</b> is an information depending on third party cou
 DolibarrDemo=Dolibarr ERP/CRM demo
 StatsByNumberOfUnits=Statistics in number of products/services units
 StatsByNumberOfEntities=Statistics in number of referring entities
-NumberOfProposals=Number of proposals in past 12 months
-NumberOfCustomerOrders=Number of customer orders in past 12 months
-NumberOfCustomerInvoices=Number of customer invoices in past 12 months
-NumberOfSupplierProposals=Number of supplier proposals in past 12 months
-NumberOfSupplierOrders=Number of supplier orders in past 12 months
-NumberOfSupplierInvoices=Number of supplier invoices in past 12 months
-NumberOfUnitsProposals=Number of units on proposals in past 12 months
-NumberOfUnitsCustomerOrders=Number of units on customer orders in past 12 months
-NumberOfUnitsCustomerInvoices=Number of units on customer invoices in past 12 months
-NumberOfUnitsSupplierProposals=Number of units on supplier proposals in past 12 months
-NumberOfUnitsSupplierOrders=Number of units on supplier orders in past 12 months
-NumberOfUnitsSupplierInvoices=Number of units on supplier invoices in past 12 months
+NumberOfProposals=Number of proposals
+NumberOfCustomerOrders=Number of customer orders
+NumberOfCustomerInvoices=Number of customer invoices
+NumberOfSupplierProposals=Number of supplier proposals
+NumberOfSupplierOrders=Number of supplier orders
+NumberOfSupplierInvoices=Number of supplier invoices
+NumberOfUnitsProposals=Number of units on proposals
+NumberOfUnitsCustomerOrders=Number of units on customer orders
+NumberOfUnitsCustomerInvoices=Number of units on customer invoices
+NumberOfUnitsSupplierProposals=Number of units on supplier proposals
+NumberOfUnitsSupplierOrders=Number of units on supplier orders
+NumberOfUnitsSupplierInvoices=Number of units on supplier invoices
 EMailTextInterventionAddedContact=A newintervention %s has been assigned to you.
 EMailTextInterventionValidated=The intervention %s has been validated.
 EMailTextInvoiceValidated=The invoice %s has been validated.
diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php
index 0510299fbd7..8867011101b 100644
--- a/htdocs/product/ajax/products.php
+++ b/htdocs/product/ajax/products.php
@@ -178,11 +178,11 @@ else
 
 	$idprod = (! empty($match[0]) ? $match[0] : '');
 	
-	if (! GETPOST($htmlname) && ! GETPOST($idprod))
+	if (! $htmlname && (! $idprod || ! GETPOST($idprod,'alpha')))
 		return;
 
 		// When used from jQuery, the search term is added as GET param "term".
-	$searchkey = (GETPOST($idprod) ? GETPOST($idprod) : (GETPOST($htmlname) ? GETPOST($htmlname) : ''));
+	$searchkey = (($idprod && GETPOST($idprod,'alpha')) ? GETPOST($idprod,'alpha') :  (GETPOST($htmlname, 'alpha') ? GETPOST($htmlname, 'alpha') : ''));
 
 	$form = new Form($db);
 	if (empty($mode) || $mode == 1) {  // mode=1: customer
diff --git a/htdocs/product/card.php b/htdocs/product/card.php
index 71f7cd8e7f6..7cd86404afa 100644
--- a/htdocs/product/card.php
+++ b/htdocs/product/card.php
@@ -1448,7 +1448,8 @@ else
 		    $head=product_prepare_head($object);
             $titre=$langs->trans("CardProduct".$object->type);
             $picto=($object->type== Product::TYPE_SERVICE?'service':'product');
-            dol_fiche_head($head, 'card', $titre, 0, $picto);
+            
+            dol_fiche_head($head, 'card', $titre, -1, $picto);
 
             $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?type='.$object->type.'">'.$langs->trans("BackToList").'</a>';
             $object->next_prev_filter=" fk_product_type = ".$object->type;
diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php
index 1225eb82696..d866e3ec2ae 100644
--- a/htdocs/product/class/product.class.php
+++ b/htdocs/product/class/product.class.php
@@ -2459,9 +2459,10 @@ class Product extends CommonObject
 	 *
 	 *  @param		string	$sql        Request to execute
 	 *  @param		string	$mode		'byunit'=number of unit, 'bynumber'=nb of entities
+	 *  @param      int     $year       Year (0=current year)
 	 *  @return   	array       		<0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11
 	 */
-	function _get_stats($sql,$mode)
+	function _get_stats($sql, $mode, $year=0)
 	{
 		$resql = $this->db->query($sql);
 		if ($resql)
@@ -2482,8 +2483,15 @@ class Product extends CommonObject
 			return -1;
 		}
 
-		$year = strftime('%Y',time());
-		$month = strftime('%m',time());
+		if (empty($year)) 
+		{
+		    $year = strftime('%Y',time());
+		    $month = strftime('%m',time());
+		}
+		else
+		{
+		    $month=12;    // We imagine we are at end of year, so we get last 12 month before, so all correct year.
+		}
 		$result = array();
 
 		for ($j = 0 ; $j < 12 ; $j++)
@@ -2516,9 +2524,11 @@ class Product extends CommonObject
 	 *  @param  	int		$socid                   Limit count on a particular third party id
 	 *  @param		string	$mode		             'byunit'=number of unit, 'bynumber'=nb of entities
 	 *  @param      int     $filteronproducttype     0=To filter on product only, 1=To filter on services only
+	 *  @param      int     $year                    Year (0=last 12 month)
+	 *  @param      string  $morefilter              More sql filters
 	 * 	@return   	array       		             <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11
 	 */
-	function get_nb_vente($socid, $mode, $filteronproducttype=-1)
+	function get_nb_vente($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
 	{
 		global $conf;
 		global $user;
@@ -2536,10 +2546,11 @@ class Product extends CommonObject
 		$sql.= " AND f.entity IN (".getEntity('facture', 1).")";
 		if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND f.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
 		if ($socid > 0)	$sql.= " AND f.fk_soc = $socid";
+		$sql.=$morefilter;
 		$sql.= " GROUP BY date_format(f.datef,'%Y%m')";
 		$sql.= " ORDER BY date_format(f.datef,'%Y%m') DESC";
 
-		return $this->_get_stats($sql,$mode);
+		return $this->_get_stats($sql,$mode, $year);
 	}
 
 
@@ -2549,9 +2560,11 @@ class Product extends CommonObject
 	 *  @param  	int		$socid                   Limit count on a particular third party id
 	 * 	@param		string	$mode		             'byunit'=number of unit, 'bynumber'=nb of entities
 	 *  @param      int     $filteronproducttype     0=To filter on product only, 1=To filter on services only
+	 *  @param      int     $year                    Year (0=last 12 month)
+	 *  @param      string  $morefilter              More sql filters
 	 * 	@return   	array       		             <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11
 	 */
-	function get_nb_achat($socid, $mode, $filteronproducttype=-1)
+	function get_nb_achat($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
 	{
 		global $conf;
 		global $user;
@@ -2569,11 +2582,11 @@ class Product extends CommonObject
 		$sql.= " AND f.entity IN (".getEntity('facture_fourn', 1).")";
 		if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND f.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
 		if ($socid > 0)	$sql.= " AND f.fk_soc = $socid";
+		$sql.=$morefilter;
 		$sql.= " GROUP BY date_format(f.datef,'%Y%m')";
 		$sql.= " ORDER BY date_format(f.datef,'%Y%m') DESC";
 
-		$resarray=$this->_get_stats($sql,$mode);
-		return $resarray;
+		return $this->_get_stats($sql,$mode, $year);
 	}
 
 	/**
@@ -2582,9 +2595,11 @@ class Product extends CommonObject
 	 *  @param  	int		$socid                   Limit count on a particular third party id
 	 * 	@param		string	$mode		             'byunit'=number of unit, 'bynumber'=nb of entities
 	 *  @param      int     $filteronproducttype     0=To filter on product only, 1=To filter on services only
+	 *  @param      int     $year                    Year (0=last 12 month)
+	 *  @param      string  $morefilter              More sql filters
 	 * 	@return   	array       		             <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11
 	 */
-	function get_nb_propal($socid, $mode, $filteronproducttype=-1)
+	function get_nb_propal($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
 	{
 		global $conf;
 		global $user;
@@ -2602,10 +2617,11 @@ class Product extends CommonObject
 		$sql.= " AND p.entity IN (".getEntity('propal', 1).")";
 		if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND p.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
 		if ($socid > 0)	$sql.= " AND p.fk_soc = ".$socid;
+		$sql.=$morefilter;
 		$sql.= " GROUP BY date_format(p.datep,'%Y%m')";
 		$sql.= " ORDER BY date_format(p.datep,'%Y%m') DESC";
 
-		return $this->_get_stats($sql,$mode);
+		return $this->_get_stats($sql,$mode, $year);
 	}
 
 	/**
@@ -2614,9 +2630,11 @@ class Product extends CommonObject
 	 *  @param  	int		$socid                   Limit count on a particular third party id
 	 * 	@param		string	$mode		             'byunit'=number of unit, 'bynumber'=nb of entities
 	 *  @param      int     $filteronproducttype     0=To filter on product only, 1=To filter on services only
+	 *  @param      int     $year                    Year (0=last 12 month)
+	 *  @param      string  $morefilter              More sql filters
 	 * 	@return   	array       		             <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11
 	 */
-	function get_nb_propalsupplier($socid, $mode, $filteronproducttype=-1)
+	function get_nb_propalsupplier($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
 	{
 		global $conf;
 		global $user;
@@ -2634,10 +2652,11 @@ class Product extends CommonObject
 		$sql.= " AND p.entity IN (".getEntity('propal', 1).")";
 		if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND p.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
 		if ($socid > 0)	$sql.= " AND p.fk_soc = ".$socid;
+		$sql.=$morefilter;
 		$sql.= " GROUP BY date_format(p.date_valid,'%Y%m')";
 		$sql.= " ORDER BY date_format(p.date_valid,'%Y%m') DESC";
 
-		return $this->_get_stats($sql,$mode);
+		return $this->_get_stats($sql,$mode, $year);
 	}
 	
 	/**
@@ -2646,9 +2665,11 @@ class Product extends CommonObject
 	 *  @param  	int		$socid                   Limit count on a particular third party id
 	 *  @param		string	$mode		             'byunit'=number of unit, 'bynumber'=nb of entities
 	 *  @param      int     $filteronproducttype     0=To filter on product only, 1=To filter on services only
+	 *  @param      int     $year                    Year (0=last 12 month)
+	 *  @param      string  $morefilter              More sql filters
 	 * 	@return   	array       		             <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11
 	 */
-	function get_nb_order($socid, $mode, $filteronproducttype=-1)
+	function get_nb_order($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
 	{
 		global $conf, $user;
 
@@ -2665,10 +2686,11 @@ class Product extends CommonObject
 		$sql.= " AND c.entity IN (".getEntity('commande', 1).")";
 		if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
 		if ($socid > 0)	$sql.= " AND c.fk_soc = ".$socid;
+		$sql.=$morefilter;
 		$sql.= " GROUP BY date_format(c.date_commande,'%Y%m')";
 		$sql.= " ORDER BY date_format(c.date_commande,'%Y%m') DESC";
 
-		return $this->_get_stats($sql,$mode);
+		return $this->_get_stats($sql,$mode, $year);
 	}
 
 	/**
@@ -2677,9 +2699,11 @@ class Product extends CommonObject
 	 *  @param  	int		$socid                   Limit count on a particular third party id
 	 *  @param		string	$mode		             'byunit'=number of unit, 'bynumber'=nb of entities
 	 *  @param      int     $filteronproducttype     0=To filter on product only, 1=To filter on services only
+	 *  @param      int     $year                    Year (0=last 12 month)
+	 *  @param      string  $morefilter              More sql filters
 	 * 	@return   	array       		             <0 if KO, result[month]=array(valuex,valuey) where month is 0 to 11
 	 */
-	function get_nb_ordersupplier($socid, $mode, $filteronproducttype=-1)
+	function get_nb_ordersupplier($socid, $mode, $filteronproducttype=-1, $year=0, $morefilter='')
 	{
 		global $conf, $user;
 
@@ -2696,10 +2720,11 @@ class Product extends CommonObject
 		$sql.= " AND c.entity IN (".getEntity('supplier_order', 1).")";
 		if (!$user->rights->societe->client->voir && !$socid) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
 		if ($socid > 0)	$sql.= " AND c.fk_soc = ".$socid;
+		$sql.=$morefilter;
 		$sql.= " GROUP BY date_format(c.date_commande,'%Y%m')";
 		$sql.= " ORDER BY date_format(c.date_commande,'%Y%m') DESC";
 
-		return $this->_get_stats($sql,$mode);
+		return $this->_get_stats($sql,$mode, $year);
 	}
 
 	/**
diff --git a/htdocs/product/composition/card.php b/htdocs/product/composition/card.php
index 37068a1daca..aa1cf4137e9 100644
--- a/htdocs/product/composition/card.php
+++ b/htdocs/product/composition/card.php
@@ -193,7 +193,7 @@ llxHeader('', $title, $helpurl);
 $head=product_prepare_head($object);
 $titre=$langs->trans("CardProduct".$object->type);
 $picto=($object->type==Product::TYPE_SERVICE?'service':'product');
-dol_fiche_head($head, 'subproduct', $titre, 0, $picto);
+dol_fiche_head($head, 'subproduct', $titre, -1, $picto);
 
 
 if ($id > 0 || ! empty($ref))
@@ -209,48 +209,47 @@ if ($id > 0 || ! empty($ref))
 		
         if ($object->type!=Product::TYPE_SERVICE || empty($conf->global->PRODUIT_MULTIPRICES))
         {
+            print '<div class="fichecenter">';
     	    print '<div class="underbanner clearboth"></div>';	
             print '<table class="border tableforfield" width="100%">';
-        }
         
-		// Nature
-		if ($object->type!=Product::TYPE_SERVICE)
-		{
-			print '<tr><td>'.$langs->trans("Nature").'</td><td>';
-			print $object->getLibFinished();
-			print '</td></tr>';
-		}
-
-		if (empty($conf->global->PRODUIT_MULTIPRICES))
-		{
-		    // Price
-			print '<tr><td>'.$langs->trans("SellingPrice").'</td><td>';
-			if ($object->price_base_type == 'TTC')
-			{
-				print price($object->price_ttc).' '.$langs->trans($object->price_base_type);
-			}
-			else
-			{
-				print price($object->price).' '.$langs->trans($object->price_base_type?$object->price_base_type:'HT');
-			}
-			print '</td></tr>';
-
-			// Price minimum
-			print '<tr><td>'.$langs->trans("MinPrice").'</td><td>';
-			if ($object->price_base_type == 'TTC')
-			{
-				print price($object->price_min_ttc).' '.$langs->trans($object->price_base_type);
-			}
-			else
-			{
-				print price($object->price_min).' '.$langs->trans($object->price_base_type?$object->price_base_type:'HT');
-			}
-			print '</td></tr>';
-		}
-
-        if ($object->type!=Product::TYPE_SERVICE || empty($conf->global->PRODUIT_MULTIPRICES))
-        {
-		  print '</table>';
+    		// Nature
+    		if ($object->type!=Product::TYPE_SERVICE)
+    		{
+    			print '<tr><td>'.$langs->trans("Nature").'</td><td>';
+    			print $object->getLibFinished();
+    			print '</td></tr>';
+    		}
+    
+    		if (empty($conf->global->PRODUIT_MULTIPRICES))
+    		{
+    		    // Price
+    			print '<tr><td>'.$langs->trans("SellingPrice").'</td><td>';
+    			if ($object->price_base_type == 'TTC')
+    			{
+    				print price($object->price_ttc).' '.$langs->trans($object->price_base_type);
+    			}
+    			else
+    			{
+    				print price($object->price).' '.$langs->trans($object->price_base_type?$object->price_base_type:'HT');
+    			}
+    			print '</td></tr>';
+    
+    			// Price minimum
+    			print '<tr><td>'.$langs->trans("MinPrice").'</td><td>';
+    			if ($object->price_base_type == 'TTC')
+    			{
+    				print price($object->price_min_ttc).' '.$langs->trans($object->price_base_type);
+    			}
+    			else
+    			{
+    				print price($object->price_min).' '.$langs->trans($object->price_base_type?$object->price_base_type:'HT');
+    			}
+    			print '</td></tr>';
+    		}
+
+            print '</table>';
+            print '</div>';
         }
 
 		dol_fiche_end();
@@ -271,7 +270,7 @@ if ($id > 0 || ! empty($ref))
 
 		//if (count($prodsfather) > 0)
 		//{
-			print load_fiche_titre($langs->trans("ProductParentList"),'','').'<br>';
+			print load_fiche_titre($langs->trans("ProductParentList"),'','');
 			print '<table class="centpercent noborder">';
 			print '<tr class="liste_titre">';
 			print '<td>'.$langs->trans('ParentProducts').'</td>';
@@ -320,7 +319,7 @@ if ($id > 0 || ! empty($ref))
 		//if (count($prods_arbo) > 0)
 		//{
 			$atleastonenotdefined=0;
-			print load_fiche_titre($langs->trans("ProductAssociationList"),'','').'<br>';
+			print load_fiche_titre($langs->trans("ProductAssociationList"),'','');
 
 			print '<form name="formComposedProduct" action="'.$_SERVER['PHP_SELF'].'" method="post">';
 			print '<input type="hidden" name="action" value="save_composed_product" />';
diff --git a/htdocs/product/list.php b/htdocs/product/list.php
index 7e6ae9b47f4..74f9c59cff3 100644
--- a/htdocs/product/list.php
+++ b/htdocs/product/list.php
@@ -55,6 +55,7 @@ $sall=GETPOST('sall', 'alphanohtml');
 $sref=GETPOST("sref");
 $sbarcode=GETPOST("sbarcode");
 $snom=GETPOST("snom");
+$search_type = GETPOST("search_type",'int');
 $search_sale = GETPOST("search_sale");
 $search_categ = GETPOST("search_categ",'int');
 $tosell = GETPOST("tosell", 'int');
@@ -65,7 +66,7 @@ $search_tobatch = GETPOST("search_tobatch",'int');
 $search_accountancy_code_sell = GETPOST("search_accountancy_code_sell",'alpha');
 $search_accountancy_code_buy = GETPOST("search_accountancy_code_buy",'alpha');
 $optioncss = GETPOST('optioncss','alpha');
-$type= (int) GETPOST("type","int");
+$type=(int) GETPOST("type","int");
 
 //Show/hide child products. Hidden by default
 if (!$_POST) {
@@ -114,8 +115,8 @@ if (! empty($canvas))
 }
 
 // Security check
-if ($type=='0') $result=restrictedArea($user,'produit','','','','','',$objcanvas);
-else if ($type=='1') $result=restrictedArea($user,'service','','','','','',$objcanvas);
+if ($search_type=='0') $result=restrictedArea($user,'produit','','','','','',$objcanvas);
+else if ($search_type=='1') $result=restrictedArea($user,'service','','','','','',$objcanvas);
 else $result=restrictedArea($user,'produit|service','','','','','',$objcanvas);
 
 // Define virtualdiffersfromphysical
@@ -158,7 +159,8 @@ $arrayfields=array(
     'p.ref'=>array('label'=>$langs->trans("Ref"), 'checked'=>1),
     //'pfp.ref_fourn'=>array('label'=>$langs->trans("RefSupplier"), 'checked'=>1, 'enabled'=>(! empty($conf->barcode->enabled))),
     'p.label'=>array('label'=>$langs->trans("Label"), 'checked'=>1),
-	'p.barcode'=>array('label'=>$langs->trans("Gencod"), 'checked'=>($contextpage != 'servicelist'), 'enabled'=>(! empty($conf->barcode->enabled))),
+    'p.fk_product_type'=>array('label'=>$langs->trans("Type"), 'checked'=>0, 'enabled'=>(! empty($conf->produit->enabled) && ! empty($conf->service->enabled))),
+    'p.barcode'=>array('label'=>$langs->trans("Gencod"), 'checked'=>($contextpage != 'servicelist'), 'enabled'=>(! empty($conf->barcode->enabled))),
     'p.duration'=>array('label'=>$langs->trans("Duration"), 'checked'=>($contextpage != 'productlist'), 'enabled'=>(! empty($conf->service->enabled))),
 	'p.sellprice'=>array('label'=>$langs->trans("SellingPrice"), 'checked'=>1, 'enabled'=>empty($conf->global->PRODUIT_MULTIPRICES)),
     'p.minbuyprice'=>array('label'=>$langs->trans("BuyingPriceMinShort"), 'checked'=>1, 'enabled'=>(! empty($user->rights->fournisseur->lire))),
@@ -212,6 +214,7 @@ if (empty($reshook))
     	$tosell="";
     	$tobuy="";
     	$search_tobatch='';
+    	$search_type='';
     	$search_accountancy_code_sell='';
     	$search_accountancy_code_buy='';
     	$search_array_options=array();
@@ -219,8 +222,8 @@ if (empty($reshook))
     
     // Mass actions
     $objectclass='Product';
-    if ((string) $type == '1') { $objectlabel='Services'; }
-    if ((string) $type == '0') { $objectlabel='Products'; }
+    if ((string) $search_type == '1') { $objectlabel='Services'; }
+    if ((string) $search_type == '0') { $objectlabel='Products'; }
     
     $permtoread = $user->rights->produit->lire;
     $permtodelete = $user->rights->produit->supprimer;
@@ -244,9 +247,9 @@ else
 {
 	$title=$langs->trans("ProductsAndServices");
 
-	if (isset($type))
+	if ($search_type != '' && $search_type != '-1')
 	{
-		if ($type==1)
+		if ($search_type==1)
 		{
 			$texte = $langs->trans("Services");
 		}
@@ -260,13 +263,13 @@ else
 		$texte = $langs->trans("ProductsAndServices");
 	}
 
-    $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
+    $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.fk_product_type, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
     $sql.= ' p.fk_product_type, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,';
     $sql.= ' p.tobatch, p.accountancy_code_sell, p.accountancy_code_buy,';
     $sql.= ' p.datec as date_creation, p.tms as date_update,';
     //$sql.= ' pfp.ref_fourn as ref_supplier, ';
     $sql.= ' MIN(pfp.unitprice) as minsellprice';
-	if (!empty($conf->variants->enabled) && $search_hidechildproducts && ($type === 0)) {
+	if (!empty($conf->variants->enabled) && $search_hidechildproducts && ($search_type === 0)) {
 		$sql .= ', pac.rowid prod_comb_id';
 	}
 	// Add fields from extrafields
@@ -281,17 +284,17 @@ else
    	$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price as pfp ON p.rowid = pfp.fk_product";
 	// multilang
 	if (! empty($conf->global->MAIN_MULTILANGS)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND pl.lang = '".$langs->getDefaultLang() ."'";
-	if (!empty($conf->variants->enabled) && $search_hidechildproducts && ($type === 0)) {
+	if (!empty($conf->variants->enabled) && $search_hidechildproducts && ($search_type === 0)) {
 		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_attribute_combination pac ON pac.fk_product_child = p.rowid";
 	}
 
 	$sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')';
 	if ($sall) $sql .= natural_search(array_keys($fieldstosearchall), $sall);
     // if the type is not 1, we show all products (type = 0,2,3)
-    if (dol_strlen($type))
+    if (dol_strlen($search_type) && $search_type != '-1')
     {
-    	if ($type == 1) $sql.= " AND p.fk_product_type = '1'";
-    	else $sql.= " AND p.fk_product_type <> '1'";
+    	if ($search_type == 1) $sql.= " AND p.fk_product_type = 1";
+    	else $sql.= " AND p.fk_product_type <> 1";
     }
 	if ($sref)     $sql .= natural_search('p.ref', $sref);
 	if ($snom)     $sql .= natural_search('p.label', $snom);
@@ -309,7 +312,7 @@ else
     if ($search_accountancy_code_sell)   $sql.= natural_search('p.accountancy_code_buy', $search_accountancy_code_buy);
     // Add where from extra fields
 
-	if (!empty($conf->variants->enabled) && $search_hidechildproducts && ($type === 0)) {
+	if (!empty($conf->variants->enabled) && $search_hidechildproducts && ($search_type === 0)) {
 		$sql .= " AND pac.rowid IS NULL";
 	}
 
@@ -333,7 +336,7 @@ else
     $sql.= " GROUP BY p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type,";
     $sql.= " p.fk_product_type, p.duration, p.tosell, p.tobuy, p.seuil_stock_alerte, p.desiredstock,";
     $sql.= ' p.datec, p.tms, p.entity, p.tobatch, p.accountancy_code_sell, p.accountancy_code_buy';
-	if (!empty($conf->variants->enabled) && $search_hidechildproducts && ($type === 0)) {
+	if (!empty($conf->variants->enabled) && $search_hidechildproducts && ($search_type === 0)) {
 		$sql .= ', pac.rowid';
 	}
 	// Add fields from extrafields
@@ -368,13 +371,13 @@ else
     	}
 
     	$helpurl='';
-    	if (isset($type))
+    	if ($search_type != '')
     	{
-    		if ($type == 0)
+    		if ($search_type == 0)
     		{
     			$helpurl='EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
     		}
-    		else if ($type == 1)
+    		else if ($search_type == 1)
     		{
     			$helpurl='EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
     		}
@@ -401,7 +404,8 @@ else
     	if ($fourn_id > 0) $param.=($fourn_id?"&amp;fourn_id=".$fourn_id:"");
     	if ($seach_categ) $param.=($search_categ?"&amp;search_categ=".urlencode($search_categ):"");
     	if ($type != '') $param.='&amp;type='.urlencode($type);
-		if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss);
+    	if ($search_type != '') $param.='&amp;search_type='.urlencode($search_type);
+    	if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss);
     	if ($search_tobatch) $param="&amp;search_ref_supplier=".urlencode($search_ref_supplier);
     	if ($search_accountancy_code_sell) $param="&amp;search_accountancy_code_sell=".urlencode($search_accountancy_code_sell);
     	if ($search_accountancy_code_buy) $param="&amp;search_accountancy_code_buy=".urlencode($search_accountancy_code_buy);
@@ -430,7 +434,8 @@ else
 		print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
 		print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
         print '<input type="hidden" name="page" value="'.$page.'">';
-		print '<input type="hidden" name="type" value="'.$type.'">';
+        print '<input type="hidden" name="type" value="'.$type.'">';
+        if (empty($arrayfields['p.fk_product_type']['checked'])) print '<input type="hidden" name="search_type" value="'.dol_escape_htmltag($search_type).'">';
 
 	    print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_products.png', 0, '', '', $limit);
 
@@ -480,7 +485,7 @@ else
     		}
 
 			//Show/hide child products. Hidden by default
-			if (!empty($conf->variants->enabled) && $type === 0) {
+			if (!empty($conf->variants->enabled) && $search_type === 0) {
 				$moreforfilter.='<div class="divsearchfield">';
 				$moreforfilter.= '<input type="checkbox" id="search_hidechildproducts" name="search_hidechildproducts" value="on"'.($search_hidechildproducts ? 'checked="checked"' : '').'>';
 				$moreforfilter.= ' <label for="search_hidechildproducts">'.$langs->trans('HideChildProducts').'</label>';
@@ -524,6 +529,14 @@ else
 		   		print '<input class="flat" type="text" name="snom" size="12" value="'.dol_escape_htmltag($snom).'">';
     			print '</td>';
     		}
+    		// Type
+    	    if (! empty($arrayfields['p.fk_product_type']['checked']))
+    		{
+    			print '<td class="liste_titre" align="left">';
+		   		$array=array('-1'=>'&nbsp;', '0'=>$langs->trans('Product'), '1'=>$langs->trans('Service'));
+    			print $form->selectarray('search_type', $array, $search_type);
+    			print '</td>';
+    		}
     		// Barcode
     		if (! empty($arrayfields['p.barcode']['checked']))
     		{
@@ -622,6 +635,7 @@ else
     		if (! empty($arrayfields['p.ref']['checked']))  print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"],"p.ref","",$param,"",$sortfield,$sortorder);
     		if (! empty($arrayfields['pfp.ref_fourn']['checked']))  print_liste_field_titre($arrayfields['pfp.ref_fourn']['label'], $_SERVER["PHP_SELF"],"pfp.ref_fourn","",$param,"",$sortfield,$sortorder);
     		if (! empty($arrayfields['p.label']['checked']))  print_liste_field_titre($arrayfields['p.label']['label'], $_SERVER["PHP_SELF"],"p.label","",$param,"",$sortfield,$sortorder);
+    		if (! empty($arrayfields['p.fk_product_type']['checked']))  print_liste_field_titre($arrayfields['p.fk_product_type']['label'], $_SERVER["PHP_SELF"],"p.fk_product_type","",$param,"",$sortfield,$sortorder);
     		if (! empty($arrayfields['p.barcode']['checked']))  print_liste_field_titre($arrayfields['p.barcode']['label'], $_SERVER["PHP_SELF"],"p.barcode","",$param,"",$sortfield,$sortorder);
     		if (! empty($arrayfields['p.duration']['checked']))  print_liste_field_titre($arrayfields['p.duration']['label'], $_SERVER["PHP_SELF"],"p.duration","",$param,'align="center"',$sortfield,$sortorder);
     		if (! empty($arrayfields['p.sellprice']['checked']))  print_liste_field_titre($arrayfields['p.sellprice']['label'], $_SERVER["PHP_SELF"],"","",$param,'align="right"',$sortfield,$sortorder);
@@ -690,7 +704,7 @@ else
                 $product_static->status     = $obj->tosell;
 				$product_static->entity = $obj->entity;
 
-				if (! empty($conf->stock->enabled) && $user->rights->stock->lire && $type != 1)	// To optimize call of load_stock
+				if (! empty($conf->stock->enabled) && $user->rights->stock->lire && $search_type != 1)	// To optimize call of load_stock
 				{
 				    if ($obj->fk_product_type != 1)    // Not a service
 				    {
@@ -721,7 +735,13 @@ else
 			    	print '<td>'.dol_trunc($obj->label,40).'</td>';
 			    }
 			    
-    			// Barcode
+    		    // Type
+			    if (! empty($arrayfields['p.fk_product_type']['checked']))
+			    {
+			    	print '<td>'.$obj->fk_product_type.'</td>';
+			    }
+			    
+			    // Barcode
 			    if (! empty($arrayfields['p.barcode']['checked']))
 			    {
     				print '<td>'.$obj->barcode.'</td>';
diff --git a/htdocs/product/stats/card.php b/htdocs/product/stats/card.php
index d0a85756c04..0477491518c 100644
--- a/htdocs/product/stats/card.php
+++ b/htdocs/product/stats/card.php
@@ -1,6 +1,6 @@
 <?php
 /* Copyright (C) 2001-2007	Rodolphe Quiedeville	<rodolphe@quiedeville.org>
- * Copyright (c) 2004-2015	Laurent Destailleur		<eldy@users.sourceforge.net>
+ * Copyright (c) 2004-2017	Laurent Destailleur		<eldy@users.sourceforge.net>
  * Copyright (C) 2005-2012	Regis Houssin			<regis.houssin@capnetworks.com>
  * Copyright (C) 2005		Eric Seigne				<eric.seigne@ryxeo.com>
  * Copyright (C) 2013		Juanjo Menent			<jmenent@2byte.es>
@@ -30,6 +30,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
+require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
 
 $WIDTH=DolGraph::getDefaultGraphSizeForStats('width',380);
 $HEIGHT=DolGraph::getDefaultGraphSizeForStats('height',160);
@@ -43,6 +45,9 @@ $langs->load("other");
 $id		= GETPOST('id','int');         // For this page, id can also be 'all'
 $ref	= GETPOST('ref');
 $mode	= (GETPOST('mode') ? GETPOST('mode') : 'byunit');
+$search_year   = GETPOST('search_year','int');
+$search_categ  = GETPOST('search_categ','int');
+
 $error	= 0;
 $mesg	= '';
 $graphfiles=array();
@@ -55,348 +60,380 @@ $fieldvalue = (! empty($id) ? $id : $ref);
 $fieldtype = (! empty($ref) ? 'ref' : 'rowid');
 $result=restrictedArea($user,'produit|service',$fieldvalue,'product&product','','',$fieldtype);
 
+$tmp=dol_getdate(dol_now());
+$currentyear=$tmp['year'];
+if (empty($search_year)) $search_year=$currentyear;
+
+
+/*
+ * Actions
+ */
+
+// None
+
 
 /*
  *	View
  */
 
 $form = new Form($db);
+$htmlother = new FormOther($db);
 
-if (! empty($id) || ! empty($ref) || GETPOST('id') == 'all')
+$object = new Product($db);
+if (! $id)
 {
-	$object = new Product($db);
-    if (GETPOST('id') == 'all')
+    llxHeader("",$langs->trans("ProductStatistics"));
+
+    $type = GETPOST('type','int');
+
+   	$helpurl='';
+    if ($type == '0')
+    {
+        $helpurl='EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
+        //$title=$langs->trans("StatisticsOfProducts");
+        $title=$langs->trans("Statistics");
+    }
+    else if ($type == '1')
     {
-        llxHeader("",$langs->trans("ProductStatistics"));
-
-   	    $type = GETPOST('type');
-
-       	$helpurl='';
-        if ($type == '0')
-        {
-            $helpurl='EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
-            //$title=$langs->trans("StatisticsOfProducts");
-            $title=$langs->trans("Statistics");
-        }
-        else if ($type == '1')
-        {
-            $helpurl='EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
-            //$title=$langs->trans("StatisticsOfServices");
-            $title=$langs->trans("Statistics");
-        }
-        else
-        {
-            $helpurl='EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
-            //$title=$langs->trans("StatisticsOfProductsOrServices");
-            $title=$langs->trans("Statistics");
-        }
-
-        print load_fiche_titre($title, $mesg,'title_products.png');
+        $helpurl='EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
+        //$title=$langs->trans("StatisticsOfServices");
+        $title=$langs->trans("Statistics");
     }
     else
     {
-        $result = $object->fetch($id,$ref);
-
-		$title = $langs->trans('ProductServiceCard');
-		$helpurl = '';
-		$shortlabel = dol_trunc($object->label,16);
-		if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT))
-		{
-			$title = $langs->trans('Product')." ". $shortlabel ." - ".$langs->trans('Statistics');
-			$helpurl='EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
-		}
-		if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE))
-		{
-			$title = $langs->trans('Service')." ". $shortlabel ." - ".$langs->trans('Statistics');
-			$helpurl='EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
-		}
-
-		llxHeader('', $title, $helpurl);
+        $helpurl='EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
+        //$title=$langs->trans("StatisticsOfProductsOrServices");
+        $title=$langs->trans("Statistics");
     }
 
+    print load_fiche_titre($title, $mesg,'title_products.png');
+}
+else
+{
+    $result = $object->fetch($id,$ref);
 
-	if ($result && (! empty($id) || ! empty($ref)))
+	$title = $langs->trans('ProductServiceCard');
+	$helpurl = '';
+	$shortlabel = dol_trunc($object->label,16);
+	if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT))
 	{
-		$head=product_prepare_head($object);
-		$titre=$langs->trans("CardProduct".$object->type);
-		$picto=($object->type==Product::TYPE_SERVICE?'service':'product');
-
-		dol_fiche_head($head, 'stats', $titre, 0, $picto);
-
-		$linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php">'.$langs->trans("BackToList").'</a>';
-		
-        dol_banner_tab($object, 'ref', $linkback, ($user->societe_id?0:1), 'ref', '', '', '', 0, '', '', 1);
-
-        dol_fiche_end();
+		$title = $langs->trans('Product')." ". $shortlabel ." - ".$langs->trans('Statistics');
+		$helpurl='EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
 	}
-	if (GETPOST('id') == 'all')
+	if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE))
 	{
-        $h=0;
-        $head = array();
-
-        $head[$h][0] = DOL_URL_ROOT.'/product/stats/card.php?id=all';
-        $head[$h][1] = $langs->trans("Chart");
-        $head[$h][2] = 'chart';
-        $h++;
-
-    	$title = $langs->trans("ListProductServiceByPopularity");
-        if ((string) $type == '1') {
-        	$title = $langs->trans("ListServiceByPopularity");
-        }
-        if ((string) $type == '0') {
-        	$title = $langs->trans("ListProductByPopularity");
-        }
-
-        $head[$h][0] = DOL_URL_ROOT.'/product/popuprop.php'.($type != ''?'?type='.$type:'');
-        $head[$h][1] = $title;
-        $head[$h][2] = 'popularityprop';
-        $h++;
-
-        dol_fiche_head($head,'chart',$langs->trans("Statistics"));
+		$title = $langs->trans('Service')." ". $shortlabel ." - ".$langs->trans('Statistics');
+		$helpurl='EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
 	}
 
+	llxHeader('', $title, $helpurl);
+}
 
-	if ($result || GETPOST('id') == 'all')
-	{
-	    if (GETPOST('id') == 'all')
-	    {
-    		// Choice of type of product
-    		if (! empty($conf->dol_use_jmobile)) print "\n".'<div class="fichecenter"><div class="nowrap">'."\n";
-
-    		if ((string) $type != '0') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).'&type=0'.($mode?'&mode='.$mode:'').'">';
-    		else print img_picto('','tick').' ';
-    		print $langs->trans("Products");
-    		if ((string) $type != '0') print '</a>';
-
-    		if (! empty($conf->dol_use_jmobile)) print '</div>'."\n".'<div class="nowrap">'."\n";
-    		else print ' &nbsp; / &nbsp; ';
-
-    		if ((string) $type != '1') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).'&type=1'.($mode?'&mode='.$mode:'').'">';
-    		else print img_picto('','tick').' ';
-    		print $langs->trans("Services");
-    		if ((string) $type != '1') print '</a>';
-
-    		if (! empty($conf->dol_use_jmobile)) print '</div>'."\n".'<div class="nowrap">'."\n";
-    		else print ' &nbsp; / &nbsp; ';
-
-    		if ((string) $type == '0' || (string) $type == '1') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).($mode?'&mode='.$mode:'').'">';
-    		else print img_picto('','tick').' ';
-    		print $langs->trans("ProductsAndServices");
-    		if ((string) $type == '0' || (string) $type == '1') print '</a>';
-
-    		if (! empty($conf->dol_use_jmobile)) print '</div></div>';
-    		else print '<br>';
-    		print '<br>';
-	    }
-
-		// Choice of stats mode (byunit or bynumber)
-		if (! empty($conf->dol_use_jmobile)) print "\n".'<div class="fichecenter"><div class="nowrap">'."\n";
-
-		if ($mode == 'bynumber') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).($type != '' ? '&type='.$type:'').'&mode=byunit">';
-		else print img_picto('','tick').' ';
-		print $langs->trans("StatsByNumberOfUnits");
-		if ($mode == 'bynumber') print '</a>';
-
-		if (! empty($conf->dol_use_jmobile)) print '</div>'."\n".'<div class="nowrap">'."\n";
-		else print ' &nbsp; / &nbsp; ';
-
-		if ($mode == 'byunit') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).($type != '' ? '&type='.$type:'').'&mode=bynumber">';
-		else print img_picto('','tick').' ';
-		print $langs->trans("StatsByNumberOfEntities");
-		if ($mode == 'byunit') print '</a>';
-
-		if (! empty($conf->dol_use_jmobile)) print '</div></div>';
-		else print '<br>';
-		print '<br>';
 
-		//print '<table width="100%">';
+if ($result && (! empty($id) || ! empty($ref)))
+{
+	$head=product_prepare_head($object);
+	$titre=$langs->trans("CardProduct".$object->type);
+	$picto=($object->type==Product::TYPE_SERVICE?'service':'product');
+
+	dol_fiche_head($head, 'stats', $titre, -1, $picto);
 
-		// Generation des graphs
-    	$dir = (! empty($conf->product->multidir_temp[$object->entity])?$conf->product->multidir_temp[$object->entity]:$conf->service->multidir_temp[$object->entity]);
-		if ($object->id > 0)  // We are on statistics for a dedicated product
-		{
-    		if (! file_exists($dir.'/'.$object->id))
+	$linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php">'.$langs->trans("BackToList").'</a>';
+	
+    dol_banner_tab($object, 'ref', $linkback, ($user->societe_id?0:1), 'ref', '', '', '', 0, '', '', 1);
+
+    dol_fiche_end();
+}
+if (empty($id) & empty($ref))
+{
+    $h=0;
+    $head = array();
+
+    $head[$h][0] = DOL_URL_ROOT.'/product/stats/card.php'.($type != ''?'?type='.$type:'');
+    $head[$h][1] = $langs->trans("Chart");
+    $head[$h][2] = 'chart';
+    $h++;
+
+	$title = $langs->trans("ListProductServiceByPopularity");
+    if ((string) $type == '1') {
+    	$title = $langs->trans("ListServiceByPopularity");
+    }
+    if ((string) $type == '0') {
+    	$title = $langs->trans("ListProductByPopularity");
+    }
+
+    $head[$h][0] = DOL_URL_ROOT.'/product/popuprop.php'.($type != ''?'?type='.$type:'');
+    $head[$h][1] = $title;
+    $head[$h][2] = 'popularityprop';
+    $h++;
+
+    dol_fiche_head($head, 'chart', $langs->trans("Statistics"), -1);
+}
+
+
+if ($result || empty($id))
+{
+        print '<form name="stats" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
+        print '<input type="hidden" name="id" value="'.$id.'">';
+        
+    	print '<table class="noborder" width="100%">';
+    	print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
+
+    	if (empty($id))
+    	{
+        	// Type
+    		print '<tr><td class="titlefield">'.$langs->trans("ProductsAndServices").'</td><td>';
+    		$array=array('-1'=>'&nbsp;', '0'=>$langs->trans('Product'), '1'=>$langs->trans('Service'));
+    		print $form->selectarray('type', $array, $type);
+    		print '</td></tr>';
+		
+    		// Tag
+    		if ($conf->categorie->enabled)
     		{
-    			if (dol_mkdir($dir.'/'.$object->id) < 0)
-    			{
-    				$mesg = $langs->trans("ErrorCanNotCreateDir",$dir);
-    				$error++;
-    			}
+        		print '<tr><td class="titlefield">'.$langs->trans("Categories").'</td><td>';
+        		//$moreforfilter.='<div class="divsearchfield">';
+        		$moreforfilter.=$htmlother->select_categories(Categorie::TYPE_PRODUCT,$search_categ,'search_categ',1);
+        		//$moreforfilter.='</div>';
+        		print $moreforfilter;
+        		print '</td></tr>';
     		}
+    	}
+		
+		// Year
+		print '<tr><td class="titlefield">'.$langs->trans("Year").'</td><td>';
+		$arrayyears=array();
+		for ($year = $currentyear - 10; $year < $currentyear + 10 ; $year++)
+		{
+		    $arrayyears[$year]=$year;
 		}
+		if (! in_array($year,$arrayyears)) $arrayyears[$year]=$year;
+		if (! in_array($nowyear,$arrayyears)) $arrayyears[$nowyear]=$nowyear;
+		arsort($arrayyears);
+		print $form->selectarray('search_year',$arrayyears,$search_year,0);
+		print '</td></tr>';
+		print '</table>';
+		print '<div class="center"><input type="submit" name="submit" class="button" value="'.$langs->trans("Refresh").'"></div>';
+		print '</form>';
+		
+		print '<br>';
+    
 
-		if($conf->propal->enabled) {
-			$graphfiles['propal']=array('modulepart'=>'productstats_proposals',
-			'file' => $object->id.'/propal12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
-			'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsProposals"):$langs->transnoentitiesnoconv("NumberOfProposals")));
-		}
-
-		if($conf->supplier_proposal->enabled) {
-			$graphfiles['proposalssuppliers']=array('modulepart'=>'productstats_proposalssuppliers',
-			'file' => $object->id.'/proposalssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
-			'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierProposals"):$langs->transnoentitiesnoconv("NumberOfSupplierProposals")));
-		}
+	// Choice of stats mode (byunit or bynumber)
+	if (! empty($conf->dol_use_jmobile)) print "\n".'<div class="fichecenter"><div class="nowrap">'."\n";
 
-		if($conf->order->enabled) {
-			$graphfiles['orders']=array('modulepart'=>'productstats_orders',
-			'file' => $object->id.'/orders12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
-			'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsCustomerOrders"):$langs->transnoentitiesnoconv("NumberOfCustomerOrders")));
-		}
+	if ($mode == 'bynumber') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).($type != '' ? '&type='.$type:'').'&mode=byunit&search_year='.$search_year.'">';
+	else print img_picto('','tick').' ';
+	print $langs->trans("StatsByNumberOfUnits");
+	if ($mode == 'bynumber') print '</a>';
 
-		if($conf->fournisseur->enabled) {
-			$graphfiles['orderssuppliers']=array('modulepart'=>'productstats_orderssuppliers',
-			'file' => $object->id.'/orderssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
-			'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierOrders"):$langs->transnoentitiesnoconv("NumberOfSupplierOrders")));
-		}
+	if (! empty($conf->dol_use_jmobile)) print '</div>'."\n".'<div class="nowrap">'."\n";
+	else print ' &nbsp; / &nbsp; ';
 
-		if($conf->facture->enabled) {
-			$graphfiles['invoices']=array('modulepart'=>'productstats_invoices',
-			'file' => $object->id.'/invoices12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
-			'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsCustomerInvoices"):$langs->transnoentitiesnoconv("NumberOfCustomerInvoices")));
+	if ($mode == 'byunit') print '<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).($type != '' ? '&type='.$type:'').'&mode=bynumber&search_year='.$search_year.'">';
+	else print img_picto('','tick').' ';
+	print $langs->trans("StatsByNumberOfEntities");
+	if ($mode == 'byunit') print '</a>';
 
-			$graphfiles['invoicessuppliers']=array('modulepart'=>'productstats_invoicessuppliers',
-			'file' => $object->id.'/invoicessuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.'.png',
-			'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierInvoices"):$langs->transnoentitiesnoconv("NumberOfSupplierInvoices")));
-		}
+	if (! empty($conf->dol_use_jmobile)) print '</div></div>';
+	else print '<br>';
+	print '<br>';
 
-		$px = new DolGraph();
+	//print '<table width="100%">';
 
-		if (! $error && count($graphfiles)>0)
+	// Generation des graphs
+	$dir = (! empty($conf->product->multidir_temp[$object->entity])?$conf->product->multidir_temp[$object->entity]:$conf->service->multidir_temp[$object->entity]);
+	if ($object->id > 0)  // We are on statistics for a dedicated product
+	{
+		if (! file_exists($dir.'/'.$object->id))
 		{
-			$mesg = $px->isGraphKo();
-			if (! $mesg)
+			if (dol_mkdir($dir.'/'.$object->id) < 0)
 			{
-				foreach($graphfiles as $key => $val)
-				{
-					if (! $graphfiles[$key]['file']) continue;
-
-					$graph_data = array();
-
-					if (dol_is_file($dir . '/' . $graphfiles[$key]['file']))
-					{
-    					// TODO Load cachefile $graphfiles[$key]['file']
-					}
-					else
-					{
-    					if ($key == 'propal')             $graph_data = $object->get_nb_propal($socid,$mode,((string) $type != '' ? $type : -1));
-    					if ($key == 'orders')             $graph_data = $object->get_nb_order($socid,$mode,((string) $type != '' ? $type : -1));
-    					if ($key == 'invoices')           $graph_data = $object->get_nb_vente($socid,$mode,((string) $type != '' ? $type : -1));
-    					if ($key == 'proposalssuppliers') $graph_data = $object->get_nb_propalsupplier($socid,$mode,((string) $type != '' ? $type : -1));
-    					if ($key == 'invoicessuppliers')  $graph_data = $object->get_nb_achat($socid,$mode,((string) $type != '' ? $type : -1));
-    					if ($key == 'orderssuppliers')    $graph_data = $object->get_nb_ordersupplier($socid,$mode,((string) $type != '' ? $type : -1));
-
-    					// TODO Save cachefile $graphfiles[$key]['file']
-					}
-
-					if (is_array($graph_data))
-					{
-						$px->SetData($graph_data);
-						$px->SetYLabel($graphfiles[$key]['label']);
-						$px->SetMaxValue($px->GetCeilMaxValue()<0?0:$px->GetCeilMaxValue());
-						$px->SetMinValue($px->GetFloorMinValue()>0?0:$px->GetFloorMinValue());
-						$px->SetWidth($WIDTH);
-						$px->SetHeight($HEIGHT);
-						$px->SetHorizTickIncrement(1);
-						$px->SetPrecisionY(0);
-						$px->SetShading(3);
-						//print 'x '.$key.' '.$graphfiles[$key]['file'];
-
-						$url=DOL_URL_ROOT.'/viewimage.php?modulepart='.$graphfiles[$key]['modulepart'].'&entity='.$object->entity.'&file='.urlencode($graphfiles[$key]['file']);
-						$px->draw($dir."/".$graphfiles[$key]['file'],$url);
-
-						$graphfiles[$key]['output']=$px->show();
-					}
-					else
-					{
-						dol_print_error($db,'Error for calculating graph on key='.$key.' - '.$object->error);
-					}
-				}
+				$mesg = $langs->trans("ErrorCanNotCreateDir",$dir);
+				$error++;
 			}
-
-			$mesg = $langs->trans("ChartGenerated");
 		}
+	}
+
+	if($conf->propal->enabled) {
+		$graphfiles['propal']=array('modulepart'=>'productstats_proposals',
+		'file' => $object->id.'/propal12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year?'_year'.$search_year:'').'.png',
+		'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsProposals"):$langs->transnoentitiesnoconv("NumberOfProposals")));
+	}
+
+	if($conf->supplier_proposal->enabled) {
+		$graphfiles['proposalssuppliers']=array('modulepart'=>'productstats_proposalssuppliers',
+		'file' => $object->id.'/proposalssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year?'_year'.$search_year:'').'.png',
+		'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierProposals"):$langs->transnoentitiesnoconv("NumberOfSupplierProposals")));
+	}
+
+	if($conf->order->enabled) {
+		$graphfiles['orders']=array('modulepart'=>'productstats_orders',
+		'file' => $object->id.'/orders12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year?'_year'.$search_year:'').'.png',
+		'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsCustomerOrders"):$langs->transnoentitiesnoconv("NumberOfCustomerOrders")));
+	}
+
+	if($conf->fournisseur->enabled) {
+		$graphfiles['orderssuppliers']=array('modulepart'=>'productstats_orderssuppliers',
+		'file' => $object->id.'/orderssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year?'_year'.$search_year:'').'.png',
+		'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierOrders"):$langs->transnoentitiesnoconv("NumberOfSupplierOrders")));
+	}
+
+	if($conf->facture->enabled) {
+		$graphfiles['invoices']=array('modulepart'=>'productstats_invoices',
+		'file' => $object->id.'/invoices12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year?'_year'.$search_year:'').'.png',
+		'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsCustomerInvoices"):$langs->transnoentitiesnoconv("NumberOfCustomerInvoices")));
+
+		$graphfiles['invoicessuppliers']=array('modulepart'=>'productstats_invoicessuppliers',
+		'file' => $object->id.'/invoicessuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year?'_year'.$search_year:'').'.png',
+		'label' => ($mode=='byunit'?$langs->transnoentitiesnoconv("NumberOfUnitsSupplierInvoices"):$langs->transnoentitiesnoconv("NumberOfSupplierInvoices")));
+	}
+
+	$px = new DolGraph();
 
-		// Show graphs
-		$i=0;
-		if ( count($graphfiles)>0)
+	if (! $error && count($graphfiles)>0)
+	{
+		$mesg = $px->isGraphKo();
+		if (! $mesg)
 		{
 			foreach($graphfiles as $key => $val)
 			{
 				if (! $graphfiles[$key]['file']) continue;
-	
-				if ($graphfiles == 'propal' && ! $user->rights->propale->lire) continue;
-				if ($graphfiles == 'order' && ! $user->rights->commande->lire) continue;
-				if ($graphfiles == 'invoices' && ! $user->rights->facture->lire) continue;
-				if ($graphfiles == 'proposals_suppliers' && ! $user->rights->supplier_proposal->lire) continue;
-				if ($graphfiles == 'invoices_suppliers' && ! $user->rights->fournisseur->facture->lire) continue;
-				if ($graphfiles == 'orders_suppliers' && ! $user->rights->fournisseur->commande->lire) continue;
-	
-	
-				if ($i % 2 == 0)
-				{
-					print "\n".'<div class="fichecenter"><div class="fichehalfleft">'."\n";
-				}
-				else
-				{
-					print "\n".'<div class="fichehalfright"><div class="ficheaddleft">'."\n";
-				}
-	
-				// Date generation
-				if ($graphfiles[$key]['output'] && ! $px->isGraphKo())
+
+				$graph_data = array();
+
+				if (dol_is_file($dir . '/' . $graphfiles[$key]['file']))
 				{
-				    if (file_exists($dir."/".$graphfiles[$key]['file']) && filemtime($dir."/".$graphfiles[$key]['file'])) $dategenerated=$langs->trans("GeneratedOn",dol_print_date(filemtime($dir."/".$graphfiles[$key]['file']),"dayhour"));
-				    else $dategenerated=$langs->trans("GeneratedOn",dol_print_date(dol_now(),"dayhour"));
+					// TODO Load cachefile $graphfiles[$key]['file']
 				}
 				else
 				{
-				    print $dategenerated=($mesg?'<font class="error">'.$mesg.'</font>':$langs->trans("ChartNotGenerated"));
+				    $morefilters='';
+				    if ($search_categ > 0) 
+				    {
+				        $categ=new Categorie($db);
+				        $categ->fetch($search_categ);
+				        $listofprodids = $categ->getObjectsInCateg('product', 1);
+				        $morefilters=' AND d.fk_product IN ('.((is_array($listofprodids) && count($listofprodids)) ? join(',',$listofprodids):'0').')';
+				    }
+				    if ($search_categ == -2)
+				    {
+				        $morefilters=' AND d.fk_product NOT IN (SELECT cp.fk_product from '.MAIN_DB_PREFIX.'categorie_product as cp)';
+				    }
+				    
+					if ($key == 'propal')             $graph_data = $object->get_nb_propal($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
+					if ($key == 'orders')             $graph_data = $object->get_nb_order($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
+					if ($key == 'invoices')           $graph_data = $object->get_nb_vente($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
+					if ($key == 'proposalssuppliers') $graph_data = $object->get_nb_propalsupplier($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
+					if ($key == 'invoicessuppliers')  $graph_data = $object->get_nb_achat($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
+					if ($key == 'orderssuppliers')    $graph_data = $object->get_nb_ordersupplier($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
+
+					// TODO Save cachefile $graphfiles[$key]['file']
 				}
-				$linktoregenerate='<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).((string) $type != ''?'&amp;type='.$type:'').'&amp;action=recalcul&amp;mode='.$mode.'">'.img_picto($langs->trans("ReCalculate").' ('.$dategenerated.')','refresh').'</a>';
-				
-				// Show graph
-				print '<table class="noborder" width="100%">';
-				// Label
-				print '<tr class="liste_titre"><td>';
-				print $graphfiles[$key]['label'];
-				print '</td>';
-				print '<td align="right">'.$linktoregenerate.'</td>';
-				print '</tr>';
-				// Image
-				print '<tr class="impair"><td colspan="2" class="nohover" align="center">';
-				print $graphfiles[$key]['output'];
-				print '</td></tr>';
-				print '</table>';
-	
-				if ($i % 2 == 0)
+
+				if (is_array($graph_data))
 				{
-					print "\n".'</div>'."\n";
+					$px->SetData($graph_data);
+					$px->SetYLabel($graphfiles[$key]['label']);
+					$px->SetMaxValue($px->GetCeilMaxValue()<0?0:$px->GetCeilMaxValue());
+					$px->SetMinValue($px->GetFloorMinValue()>0?0:$px->GetFloorMinValue());
+					$px->SetWidth($WIDTH);
+					$px->SetHeight($HEIGHT);
+					$px->SetHorizTickIncrement(1);
+					$px->SetPrecisionY(0);
+					$px->SetShading(3);
+					//print 'x '.$key.' '.$graphfiles[$key]['file'];
+
+					$url=DOL_URL_ROOT.'/viewimage.php?modulepart='.$graphfiles[$key]['modulepart'].'&entity='.$object->entity.'&file='.urlencode($graphfiles[$key]['file']);
+					$px->draw($dir."/".$graphfiles[$key]['file'],$url);
+
+					$graphfiles[$key]['output']=$px->show();
 				}
 				else
 				{
-					print "\n".'</div></div></div>';
-					print '<div class="clear"><div class="fichecenter"><br></div></div>'."\n";
+					dol_print_error($db,'Error for calculating graph on key='.$key.' - '.$object->error);
 				}
-	
-				$i++;
 			}
 		}
-		// div not closed
-		if ($i % 2 == 1)
+
+		$mesg = $langs->trans("ChartGenerated");
+	}
+
+	// Show graphs
+	$i=0;
+	if ( count($graphfiles)>0)
+	{
+		foreach($graphfiles as $key => $val)
 		{
-			print "\n".'<div class="fichehalfright"><div class="ficheaddleft">'."\n";
-			print "\n".'</div></div></div>';
-			print '<div class="clear"><div class="fichecenter"><br></div></div>'."\n";
+			if (! $graphfiles[$key]['file']) continue;
+
+			if ($graphfiles == 'propal' && ! $user->rights->propale->lire) continue;
+			if ($graphfiles == 'order' && ! $user->rights->commande->lire) continue;
+			if ($graphfiles == 'invoices' && ! $user->rights->facture->lire) continue;
+			if ($graphfiles == 'proposals_suppliers' && ! $user->rights->supplier_proposal->lire) continue;
+			if ($graphfiles == 'invoices_suppliers' && ! $user->rights->fournisseur->facture->lire) continue;
+			if ($graphfiles == 'orders_suppliers' && ! $user->rights->fournisseur->commande->lire) continue;
+
+
+			if ($i % 2 == 0)
+			{
+				print "\n".'<div class="fichecenter"><div class="fichehalfleft">'."\n";
+			}
+			else
+			{
+				print "\n".'<div class="fichehalfright"><div class="ficheaddleft">'."\n";
+			}
+
+			// Date generation
+			if ($graphfiles[$key]['output'] && ! $px->isGraphKo())
+			{
+			    if (file_exists($dir."/".$graphfiles[$key]['file']) && filemtime($dir."/".$graphfiles[$key]['file'])) $dategenerated=$langs->trans("GeneratedOn",dol_print_date(filemtime($dir."/".$graphfiles[$key]['file']),"dayhour"));
+			    else $dategenerated=$langs->trans("GeneratedOn",dol_print_date(dol_now(),"dayhour"));
+			}
+			else
+			{
+			    print $dategenerated=($mesg?'<font class="error">'.$mesg.'</font>':$langs->trans("ChartNotGenerated"));
+			}
+			$linktoregenerate='<a href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id')?GETPOST('id'):$object->id).((string) $type != ''?'&type='.$type:'').'&action=recalcul&mode='.$mode.'&search_year='.$search_year.'&search_categ='.$search_categ.'">'.img_picto($langs->trans("ReCalculate").' ('.$dategenerated.')','refresh').'</a>';
+			
+			// Show graph
+			print '<table class="noborder" width="100%">';
+			// Label
+			print '<tr class="liste_titre"><td>';
+			print $graphfiles[$key]['label'];
+			print '</td>';
+			print '<td align="right">'.$linktoregenerate.'</td>';
+			print '</tr>';
+			// Image
+			print '<tr class="impair"><td colspan="2" class="nohover" align="center">';
+			print $graphfiles[$key]['output'];
+			print '</td></tr>';
+			print '</table>';
+
+			if ($i % 2 == 0)
+			{
+				print "\n".'</div>'."\n";
+			}
+			else
+			{
+				print "\n".'</div></div></div>';
+				print '<div class="clear"><div class="fichecenter"><br></div></div>'."\n";
+			}
+
+			$i++;
 		}
 	}
-
-	if (GETPOST('id') == 'all')
+	// div not closed
+	if ($i % 2 == 1)
 	{
-	    dol_fiche_end();
+		print "\n".'<div class="fichehalfright"><div class="ficheaddleft">'."\n";
+		print "\n".'</div></div></div>';
+		print '<div class="clear"><div class="fichecenter"><br></div></div>'."\n";
 	}
 }
-else
+
+if (! $id)
 {
-	dol_print_error();
+    dol_fiche_end();
 }
 
 llxFooter();
diff --git a/htdocs/product/stats/commande.php b/htdocs/product/stats/commande.php
index 341d002a1af..1c72d5f6615 100644
--- a/htdocs/product/stats/commande.php
+++ b/htdocs/product/stats/commande.php
@@ -94,7 +94,7 @@ if ($id > 0 || ! empty($ref))
 		$head=product_prepare_head($product);
 		$titre=$langs->trans("CardProduct".$product->type);
 		$picto=($product->type==Product::TYPE_SERVICE?'service':'product');
-		dol_fiche_head($head, 'referers', $titre, 0, $picto);
+		dol_fiche_head($head, 'referers', $titre, -1, $picto);
 
 		$reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$product,$action);    // Note that $action and $object may have been modified by hook
 		if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
diff --git a/htdocs/product/stats/commande_fournisseur.php b/htdocs/product/stats/commande_fournisseur.php
index bed3be1892f..3201e7ed2e8 100644
--- a/htdocs/product/stats/commande_fournisseur.php
+++ b/htdocs/product/stats/commande_fournisseur.php
@@ -101,7 +101,7 @@ if ($id > 0 || ! empty($ref)) {
 		$head = product_prepare_head($product);
 		$titre = $langs->trans("CardProduct" . $product->type);
 		$picto = ($product->type == Product::TYPE_SERVICE ? 'service' : 'product');
-		dol_fiche_head($head, 'referers', $titre, 0, $picto);
+		dol_fiche_head($head, 'referers', $titre, -1, $picto);
 
 		$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $product, $action); // Note that $action and $object may have been modified by hook
 		if ($reshook < 0)
diff --git a/htdocs/product/stats/contrat.php b/htdocs/product/stats/contrat.php
index 6a8183ca7de..e2f5bccc430 100644
--- a/htdocs/product/stats/contrat.php
+++ b/htdocs/product/stats/contrat.php
@@ -84,7 +84,7 @@ if ($id > 0 || ! empty($ref))
 		$head=product_prepare_head($product);
 		$titre=$langs->trans("CardProduct".$product->type);
 		$picto=($product->type==Product::TYPE_SERVICE?'service':'product');
-		dol_fiche_head($head, 'referers', $titre, 0, $picto);
+		dol_fiche_head($head, 'referers', $titre, -1, $picto);
 
 		$reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$product,$action);    // Note that $action and $object may have been modified by hook
 		if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
diff --git a/htdocs/product/stats/facture.php b/htdocs/product/stats/facture.php
index f0e5b0f13c4..506689a6001 100644
--- a/htdocs/product/stats/facture.php
+++ b/htdocs/product/stats/facture.php
@@ -111,7 +111,7 @@ if ($id > 0 || ! empty($ref))
 		$head=product_prepare_head($product);
 		$titre=$langs->trans("CardProduct".$product->type);
 		$picto=($product->type==Product::TYPE_SERVICE?'service':'product');
-		dol_fiche_head($head, 'referers', $titre, 0, $picto);
+		dol_fiche_head($head, 'referers', $titre, -1, $picto);
 
 		$reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$product,$action);    // Note that $action and $object may have been modified by hook
 		if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
diff --git a/htdocs/product/stats/facture_fournisseur.php b/htdocs/product/stats/facture_fournisseur.php
index 6fe189c7700..ac2849fefcf 100644
--- a/htdocs/product/stats/facture_fournisseur.php
+++ b/htdocs/product/stats/facture_fournisseur.php
@@ -96,7 +96,7 @@ if ($id > 0 || ! empty($ref))
 		$head = product_prepare_head($product);
 		$titre = $langs->trans("CardProduct" . $product->type);
 		$picto = ($product->type == Product::TYPE_SERVICE ? 'service' : 'product');
-		dol_fiche_head($head, 'referers', $titre, 0, $picto);
+		dol_fiche_head($head, 'referers', $titre, -1, $picto);
 
 		$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $product, $action); // Note that $action and $object may have been modified by hook
 		if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
diff --git a/htdocs/product/stats/propal.php b/htdocs/product/stats/propal.php
index 289cf3d3578..06d43838bce 100644
--- a/htdocs/product/stats/propal.php
+++ b/htdocs/product/stats/propal.php
@@ -94,7 +94,7 @@ if ($id > 0 || ! empty($ref))
 		$head = product_prepare_head($product);
 		$titre = $langs->trans("CardProduct" . $product->type);
 		$picto = ($product->type == Product::TYPE_SERVICE ? 'service' : 'product');
-		dol_fiche_head($head, 'referers', $titre, 0, $picto);
+		dol_fiche_head($head, 'referers', $titre, -1, $picto);
 
 		$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $product, $action); // Note that $action and $object may have been modified by hook
 		if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
-- 
GitLab