diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 30db4bf232f..3efd24778ad 100755 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -250,3 +250,6 @@ PriceExpressionEditorHelp3=In both product/service and supplier prices there are PriceExpressionEditorHelp4=In product/service price only: #supplier_min_price#
In supplier prices only: #supplier_quantity# and #supplier_tva_tx# PriceMode=Price mode PriceNumeric=Number +ComposedProductDecreaseStock=Decrease Stock for sub-product +ComposedProduct=Sub-product +MinSupplierPrice=Minimun supplier price diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 3f3786016e5..fe67938766d 100755 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2306,6 +2306,40 @@ class Product extends CommonObject } } + /** + * Modify composed product + * + * @param int $id_pere Id of master product + * @param int $id_fils Id of linked product + * @param int $qty Quantity + * @param int $incdec increase/descrease stock or not + * * @return int < 0 if KO, > 0 if OK + */ + function update_sousproduit($id_pere, $id_fils,$qty, $incdec=1) + { + // Clean parameters + if (! is_numeric($id_pere)) $id_pere=0; + if (! is_numeric($id_fils)) $id_fils=0; + if (! is_numeric($incdec)) $incdec=1; + if (! is_numeric($qty)) $qty=1; + + $sql = 'UPDATE '.MAIN_DB_PREFIX.'product_association SET '; + $sql.= 'qty='.$qty; + $sql.= ',incdec='.$incdec; + $sql .= ' WHERE fk_product_pere='.$id_pere.' AND fk_product_fils='.$id_fils; + + if (!$this->db->query($sql)) + { + dol_print_error($this->db); + return -1; + } + else + { + return 1; + } + + } + /** * Retire le lien entre un sousproduit et un produit/service * @@ -2633,6 +2667,8 @@ class Product extends CommonObject $nb=(! empty($desc_pere[1]) ? $desc_pere[1] :''); $type=(! empty($desc_pere[2]) ? $desc_pere[2] :''); $label=(! empty($desc_pere[3]) ? $desc_pere[3] :''); + $incdec=!empty($desc_pere[4]) ? $desc_pere[4] : 0; + if ($multiply < 1) $multiply=1; //print "XXX We add id=".$id." - label=".$label." - nb=".$nb." - multiply=".$multiply." fullpath=".$compl_path.$label."\n"; @@ -2649,7 +2685,8 @@ class Product extends CommonObject 'fullpath'=>$compl_path.$label, // Label 'type'=>$type, // Nb of units that compose parent product 'desiredstock'=>$this->desiredstock, - 'level'=>$level + 'level'=>$level, + 'incdec'=>$incdec ); // Recursive call if there is childs to child @@ -2798,7 +2835,7 @@ class Product extends CommonObject */ function getChildsArbo($id) { - $sql = "SELECT p.rowid, p.label as label, pa.qty as qty, pa.fk_product_fils as id, p.fk_product_type"; + $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"; $sql.= " WHERE p.rowid = pa.fk_product_fils"; @@ -2812,7 +2849,13 @@ class Product extends CommonObject $prods = array(); while ($rec = $this->db->fetch_array($res)) { - $prods[$rec['rowid']]= array(0=>$rec['id'],1=>$rec['qty'],2=>$rec['fk_product_type'],3=>$this->db->escape($rec['label'])); + $prods[$rec['rowid']]= array( + 0=>$rec['id'], + 1=>$rec['qty'], + 2=>$rec['fk_product_type'], + 3=>$this->db->escape($rec['label']), + 4=>$rec['incdec'] + ); //$prods[$this->db->escape($rec['label'])]= array(0=>$rec['id'],1=>$rec['qty'],2=>$rec['fk_product_type']); //$prods[$this->db->escape($rec['label'])]= array(0=>$rec['id'],1=>$rec['qty']); $listofchilds=$this->getChildsArbo($rec['id']); diff --git a/htdocs/product/composition/card.php b/htdocs/product/composition/card.php index 12553ada59a..b7c6ad45dc5 100644 --- a/htdocs/product/composition/card.php +++ b/htdocs/product/composition/card.php @@ -109,6 +109,19 @@ $cancel <> $langs->trans("Cancel") && exit; } } +else if($action==='save_composed_product') { + + $TProduct = GETPOST('TProduct', 'array'); + if(!empty($TProduct)) { + + foreach ($TProduct as $id_product => $row) { + $product->update_sousproduit($id, $id_product,$row['qty'], isset($row['incdec']) ? 1 : 0 ); + } + + } + + +} if ($cancel == $langs->trans("Cancel")) { @@ -215,7 +228,7 @@ if ($id > 0 || ! empty($ref)) { print ''; print ''.$langs->trans("ProductAssociationList").'
'; - print ''; + print ''; foreach($prods_arbo as $value) { $productstatic->id=$value['id']; @@ -246,7 +259,7 @@ if ($id > 0 || ! empty($ref)) print '
'; print ''.$langs->trans("ProductParentList").'
'; print ''; - foreach($prodsfather as $value) + foreach($prodnbsfather as $value) { $idprod= $value["id"]; $productstatic->id=$idprod;// $value["id"]; @@ -333,20 +346,43 @@ if ($id > 0 || ! empty($ref)) $atleastonenotdefined=0; print ''; } // Number of parent virtual products - print ''; diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 4cea2b7621c..39dd2ff5f67 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -341,8 +341,7 @@ class MouvementStock extends CommonObject $sql = "SELECT fk_product_pere, fk_product_fils, qty"; $sql.= " FROM ".MAIN_DB_PREFIX."product_association"; $sql.= " WHERE fk_product_pere = ".$idProduct; - // TODO Select only subproduct with incdec tag - //$sql.= " AND incdec = 1"; + $sql.= " AND incdec = 1"; dol_syslog(get_class($this)."::_createSubProduct", LOG_DEBUG); $resql=$this->db->query($sql);
'; print $langs->trans("ProductAssociationList").'
'; - print ''; + + print ''; + print ''; + print ''; + + print '
'; + + print ''; + foreach($prods_arbo as $value) { $productstatic->id=$value['id']; $productstatic->type=$value['type']; - //print '
'.$productstatic->ref.'
'; - //print $productstatic->getNomUrl(1).'
'; - //var_dump($value); - print ''; + + $class=($class=='impair')?'pair':'impair'; + + print ''; if ($value['level'] <= 1) { $notdefined=0; $productstatic->ref=$value['fullpath']; - print ''; + $nb_of_subproduct = $value['nb']; + + print ''; + + if($user->rights->produit->creer || $user->rights->service->creer) { + print ''; + print ''; + + } + else{ + print ''; + print ''; + } + + + print ''; - print ''; + print ''; + print ''; + print ''; // Real stock } print ''; } - print ''; - print ''; + print ''; - print ''; + print ''; if (! empty($conf->stock->enabled)) print ''; print ''; print '
'.$langs->trans('ComposedProduct').''.$langs->trans('Qty').''.$langs->trans('ComposedProductDecreaseStock').''.$langs->trans('MinSupplierPrice').''.$langs->trans('Price').''.$langs->trans('Stock').'
'.$productstatic->getNomUrl(1,'composition').' ('.$value['nb'].')'.$productstatic->getNomUrl(1,'composition').''.$nb_of_subproduct.''.($value['incdec']==1?'x':'' ).''; if ($product_fourn->find_min_price_product_fournisseur($productstatic->id) > 0) { @@ -367,26 +403,35 @@ if ($id > 0 || ! empty($ref)) { print '     '; } - print $productstatic->getNomUrl(1,'composition').' ('.$value['nb'].')'; - print ''; + print $productstatic->getNomUrl(1,'composition').''.$value['nb'].'  '; + print ' '; if (! empty($conf->stock->enabled)) print '
'.$langs->trans("TotalBuyingPriceMin").': '; + print '
'.$langs->trans("TotalBuyingPriceMin").': '; if ($atleastonenotdefined) print $langs->trans("Unknown").' ('.$langs->trans("SomeSubProductHaveNoPrices").')'; print ''.($atleastonenotdefined?'':price($total,'','',0,0,-1,$conf->currency)).''.($atleastonenotdefined?'':price($total,'','',0,0,-1,$conf->currency)).' 
'; + + if($user->rights->produit->creer || $user->rights->service->creer) { + print '
'; + } + + print ''; + print '
'.$langs->trans("ParentProductsNumber").''; + print '
'.$langs->trans("ParentProductsNumber").''; print $form->textwithpicto(count($prodsfather), $langs->trans('IfZeroItIsNotUsedByVirtualProduct')); print '