diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 86a11f57541..e8b32f978cb 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2897,7 +2897,7 @@ class Product extends CommonObject } /** - * reconstruit l'arborescence des categories sous la forme d'un tableau + * reconstruit l'arborescence des produits sous la forme d'un tableau * * @param int $multiply Because each sublevel must be multiplicated by parent nb * @return array $this->res @@ -2940,7 +2940,6 @@ class Product extends CommonObject * Return all Father products fo current product * * @return array Array of product - * @see getParent */ function getFather() { @@ -2985,6 +2984,8 @@ class Product extends CommonObject */ function getChildsArbo($id, $firstlevelonly=0, $level=1) { + global $alreadyfound; + $sql = "SELECT p.rowid, p.label as label, pa.qty as qty, pa.fk_product_fils as id, p.fk_product_type, pa.incdec"; $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; $sql.= ", ".MAIN_DB_PREFIX."product_association as pa"; @@ -2994,6 +2995,7 @@ class Product extends CommonObject dol_syslog(get_class($this).'::getChildsArbo id='.$id.' level='.$level, LOG_DEBUG); + if ($level == 1) $alreadyfound=array($id=>1); // We init array of found object to start of tree, so if we found it later (should not happened), we stop immediatly // Protection against infinite loop if ($level > 30) return array(); @@ -3003,9 +3005,14 @@ class Product extends CommonObject $prods = array(); while ($rec = $this->db->fetch_array($res)) { - // TODO Add check to not add ne record if already added + if (! empty($alreadyfound[$rec['rowid']])) + { + dol_syslog(get_class($this).'::getChildsArbo the product id='.$rec['rowid'].' was already found at a higher level in tree. We discard to avoid infinite loop', LOG_WARNING); + continue; + } + $alreadyfound[$rec['rowid']]=1; $prods[$rec['rowid']]= array( - 0=>$rec['id'], + 0=>$rec['rowid'], 1=>$rec['qty'], 2=>$rec['fk_product_type'], 3=>$this->db->escape($rec['label']), @@ -3015,7 +3022,7 @@ class Product extends CommonObject //$prods[$this->db->escape($rec['label'])]= array(0=>$rec['id'],1=>$rec['qty']); if (empty($firstlevelonly)) { - $listofchilds=$this->getChildsArbo($rec['id'], 0, $level + 1); + $listofchilds=$this->getChildsArbo($rec['rowid'], 0, $level + 1); foreach($listofchilds as $keyChild => $valueChild) { $prods[$rec['rowid']]['childs'][$keyChild] = $valueChild; @@ -3040,16 +3047,11 @@ class Product extends CommonObject */ function get_sousproduits_arbo() { - //$parent = $this->getParent(); $parent=array(); - $parent[$this->label]=array(0 => $this->id); - foreach($parent as $key => $value) // key=label, value[0]=id + foreach($this->getChildsArbo($this->id) as $keyChild => $valueChild) // Warning. getChildsArbo can call getChildsArbo recursively. Starting point is $value[0]=id of product { - foreach($this->getChildsArbo($value[0]) as $keyChild => $valueChild) // Warning. getChildsArbo can gell getChildsArbo recursively. - { - $parent[$key][$keyChild] = $valueChild; - } + $parent[$this->label][$keyChild] = $valueChild; } foreach($parent as $key => $value) // key=label, value is array of childs { diff --git a/htdocs/product/composition/card.php b/htdocs/product/composition/card.php index 25195f6c167..adfce7d6229 100644 --- a/htdocs/product/composition/card.php +++ b/htdocs/product/composition/card.php @@ -235,8 +235,9 @@ if ($id > 0 || ! empty($ref)) $prodsfather = $object->getFather(); // Parent Products - $object->get_sousproduits_arbo(); // Load $object->sousprod - $prods_arbo=$object->get_arbo_each_prod(); + $object->get_sousproduits_arbo(); // Load $object->sousprods + $prods_arbo=$object->get_arbo_each_prod(); + $nbofsubsubproducts=count($prods_arbo); // This include sub sub product into nb $prodschild = $object->getChildsArbo($id,1); $nbofsubproducts=count($prodschild); // This include only first level of childs @@ -379,10 +380,10 @@ if ($id > 0 || ! empty($ref)) print ''."\n"; } - else // By default, we do not show this. It makes screen very difficult to understand + else { $hide=''; - if (empty($conf->global->PRODUCT_SHOW_SUB_SUB_PRODUCTS)) $hide=' hideobject'; + if (empty($conf->global->PRODUCT_SHOW_SUB_SUB_PRODUCTS)) $hide=' hideobject'; // By default, we do not show this. It makes screen very difficult to understand $class=($class=='impair')?'pair':'impair'; print ''; @@ -394,9 +395,13 @@ if ($id > 0 || ! empty($ref)) print $productstatic->getNomUrl(1,'composition').''; print ''.$productstatic->label.''; + // Best buying price print ' '; print ' '; - + // Best selling price + print ' '; + print ' '; + if (! empty($conf->stock->enabled)) print ''; // Real stock print ''.$value['nb'].''; print ' '; diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 1d63964be1c..d8adf66bcc1 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -145,7 +145,7 @@ $arrayfields=array( '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.duration'=>array('label'=>$langs->trans("Duration"), 'checked'=>($contextpage != 'productlist'), 'enabled'=>(! empty($conf->service->enabled))), - 'p.sellprice'=>array('label'=>$titlesellprice, 'checked'=>1, 'enabled'=>empty($conf->global->PRODUIT_MULTIPRICES)), + '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))), 'p.seuil_stock_alerte'=>array('label'=>$langs->trans("StockLimit"), 'checked'=>0, 'enabled'=>(! empty($conf->stock->enabled) && $user->rights->stock->lire && $contextpage != 'service')), 'p.desiredstock'=>array('label'=>$langs->trans("DesiredStock"), 'checked'=>1, 'enabled'=>(! empty($conf->stock->enabled) && $user->rights->stock->lire && $contextpage != 'service')), @@ -425,7 +425,7 @@ else $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields - + print ''; print ''; if (! empty($arrayfields['p.ref']['checked'])) print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"],"p.ref","",$param,"",$sortfield,$sortorder); diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index a3465480b24..e330e9d8b75 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -267,19 +267,16 @@ if ($resql) print_liste_field_titre($langs->trans("StockLimit"), $_SERVER["PHP_SELF"], "p.seuil_stock_alerte",$param,"",'align="right"',$sortfield,$sortorder); print_liste_field_titre($langs->trans("DesiredStock"), $_SERVER["PHP_SELF"], "p.desiredstock",$param,"",'align="right"',$sortfield,$sortorder); print_liste_field_titre($langs->trans("PhysicalStock"), $_SERVER["PHP_SELF"], "stock_physique",$param,"",'align="right"',$sortfield,$sortorder); - - /* - * Details per warehouse - */ - - if($nb_warehouse>1) { - - foreach($warehouses_list as &$wh) { - print_liste_field_titre($wh['label'], '', '','','','align="right"'); + // Details per warehouse + if (! empty($conf->global->STOCK_DETAIL_ON_WAREHOUSE)) // TODO This should be moved into the selection of fields on page product/list (page product/stock will be removed and replaced with product/list with its own context) + { + if ($nb_warehouse>1) { + foreach($warehouses_list as &$wh) { + print_liste_field_titre($wh['label'], '', '','','','align="right"'); + } + } - } - if ($virtualdiffersfromphysical) print_liste_field_titre($langs->trans("VirtualStock"),$_SERVER["PHP_SELF"], "stock_theorique",$param,"",'align="right"',$sortfield,$sortorder); print_liste_field_titre(''); print_liste_field_titre($langs->trans("Status").' ('.$langs->trans("Sell").')',$_SERVER["PHP_SELF"], "p.tosell",$param,"",'align="right"',$sortfield,$sortorder); @@ -309,8 +306,8 @@ if ($resql) print ''; print ''; print ''; print ''; @@ -349,19 +346,17 @@ if ($resql) print $objp->stock_physique; print ''; - /* - * Details per warehouse - */ - - if($nb_warehouse>1) { - - foreach($warehouses_list as &$wh) { - - print ''; - } - + // Details per warehouse + if (! empty($conf->global->STOCK_DETAIL_ON_WAREHOUSE)) // TODO This should be moved into the selection of fields on page product/list (page product/stock will be removed and replaced with product/list with its own context) + { + if($nb_warehouse>1) { + foreach($warehouses_list as &$wh) { + + print ''; + } + } }
  '; - $searchpitco=$form->showFilterAndCheckAddButtons(0); - print $searchpitco; + $searchpitco=$form->showFilterAndCheckAddButtons(0); + print $searchpitco; print '
'; - print empty($product->stock_warehouse[$wh['id']]->real) ? '0' : $product->stock_warehouse[$wh['id']]->real; - print ''; + print empty($product->stock_warehouse[$wh['id']]->real) ? '0' : $product->stock_warehouse[$wh['id']]->real; + print '