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ódulo_Productos'; } - else if ($type == 1) + else if ($search_type == 1) { $helpurl='EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios'; } @@ -401,7 +404,8 @@ else if ($fourn_id > 0) $param.=($fourn_id?"&fourn_id=".$fourn_id:""); if ($seach_categ) $param.=($search_categ?"&search_categ=".urlencode($search_categ):""); if ($type != '') $param.='&type='.urlencode($type); - if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss); + if ($search_type != '') $param.='&search_type='.urlencode($search_type); + if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss); if ($search_tobatch) $param="&search_ref_supplier=".urlencode($search_ref_supplier); if ($search_accountancy_code_sell) $param="&search_accountancy_code_sell=".urlencode($search_accountancy_code_sell); if ($search_accountancy_code_buy) $param="&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'=>' ', '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ó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ódulo_Productos'; - //$title=$langs->trans("StatisticsOfProducts"); - $title=$langs->trans("Statistics"); - } - else if ($type == '1') - { - $helpurl='EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios'; - //$title=$langs->trans("StatisticsOfServices"); - $title=$langs->trans("Statistics"); - } - else - { - $helpurl='EN:Module_Services_En|FR:Module_Services|ES:Mó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ó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ó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ódulo_Servicios'; - } - - llxHeader('', $title, $helpurl); + $helpurl='EN:Module_Services_En|FR:Module_Services|ES:Mó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ó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ó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 ' / '; - - 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 ' / '; - - 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 ' / '; - - 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'=>' ', '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 ' / '; - 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 != ''?'&type='.$type:'').'&action=recalcul&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