diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 07b9262fafa..9b3dc1f3004 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1239,6 +1239,7 @@ class Commande extends CommonObject $line->ref = $objp->product_ref; $line->libelle = $objp->label; + $line->product_label = $objp->label; $line->product_desc = $objp->product_desc; // Description produit $line->fk_product_type = $objp->fk_product_type; // Produit ou service diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 6167d24ae74..9914814829d 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -363,6 +363,8 @@ class Expedition extends CommonObject $this->db->begin(); + $error = 0; + // Define new ref $num = "EXP".$this->id; @@ -385,51 +387,49 @@ class Expedition extends CommonObject $error++; } - if (! $error) + // If stock increment is done on sending (recommanded choice) + if (! $error && $conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_SHIPMENT) { - // If stock increment is done on sending (recommanded choice) - if ($result >= 0 && $conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_SHIPMENT) + require_once DOL_DOCUMENT_ROOT."/product/stock/class/mouvementstock.class.php"; + + // Loop on each product line to add a stock movement + // TODO possibilite d'expedier a partir d'une propale ou autre origine + $sql = "SELECT cd.fk_product, cd.subprice, ed.qty, ed.fk_entrepot"; + $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd"; + $sql.= ", ".MAIN_DB_PREFIX."expeditiondet as ed"; + $sql.= " WHERE ed.fk_expedition = ".$this->id; + $sql.= " AND cd.rowid = ed.fk_origin_line"; + + dol_syslog("Expedition::valid select details sql=".$sql); + $resql=$this->db->query($sql); + if ($resql) { - require_once DOL_DOCUMENT_ROOT."/product/stock/class/mouvementstock.class.php"; - - // Loop on each product line to add a stock movement - // TODO possibilite d'expedier a partir d'une propale ou autre origine - $sql = "SELECT cd.fk_product, cd.subprice, ed.qty, ed.fk_entrepot"; - $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd"; - $sql.= ", ".MAIN_DB_PREFIX."expeditiondet as ed"; - $sql.= " WHERE ed.fk_expedition = ".$this->id; - $sql.= " AND cd.rowid = ed.fk_origin_line"; - - dol_syslog("Expedition::valid select details sql=".$sql); - $resql=$this->db->query($sql); - if ($resql) + $num = $this->db->num_rows($resql); + $i=0; + while($i < $num) { - $num = $this->db->num_rows($resql); - $i=0; - while($i < $num) + dol_syslog("Expedition::valid movment index ".$i); + $obj = $this->db->fetch_object($resql); + + if ($this->lignes[$i]->fk_product > 0 && $this->lignes[$i]->product_type == 0) { - dol_syslog("Expedition::valid movment index ".$i); - $obj = $this->db->fetch_object($resql); - - if ($this->lignes[$i]->fk_product > 0 && $this->lignes[$i]->product_type == 0) - { - $mouvS = new MouvementStock($this->db); - // We decrement stock of product (and sub-products) - $entrepot_id = "1"; // TODO ajouter possibilite de choisir l'entrepot - $result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $obj->qty, $obj->subprice); - if ($result < 0) { $error++; } - } - - $i++; + //var_dump($this->lignes[$i]); + $mouvS = new MouvementStock($this->db); + // We decrement stock of product (and sub-products) + // We use warehouse selected for each line + $result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $obj->qty, $obj->subprice); + if ($result < 0) { $error++; break; } } + + $i++; } - else - { - $this->db->rollback(); - $this->error=$this->db->error(); - dol_syslog("Expedition::valid ".$this->error, LOG_ERR); - return -2; - } + } + else + { + $this->db->rollback(); + $this->error=$this->db->error(); + dol_syslog("Expedition::valid ".$this->error, LOG_ERR); + return -2; } } diff --git a/htdocs/expedition/fiche.php b/htdocs/expedition/fiche.php index 838218f9b90..131d5b84559 100644 --- a/htdocs/expedition/fiche.php +++ b/htdocs/expedition/fiche.php @@ -98,12 +98,13 @@ if ($_POST["action"] == 'add') for ($i = 0 ; $i < sizeof($object->lignes) ; $i++) { - $ent = "entl".$i; - $idl = "idl".$i; $qty = "qtyl".$i; - $entrepot_id = $_POST[$ent]?$_POST[$ent]:$_POST["entrepot_id"]; if ($_POST[$qty] > 0) { + $ent = "entl".$i; + $idl = "idl".$i; + $entrepot_id = isset($_POST[$ent])?$_POST[$ent]:$_POST["entrepot_id"]; + $expedition->addline($entrepot_id,$_POST[$idl],$_POST[$qty]); } } @@ -326,8 +327,10 @@ if ($_GET["action"] == 'create') $object = new $classname($db); - if ($object->fetch($origin_id)) + if ($object->fetch($origin_id)) // This include the fetch_lines { + //var_dump($object); + $soc = new Societe($db); $soc->fetch($object->socid); @@ -461,21 +464,16 @@ if ($_GET["action"] == 'create') print ''.$langs->trans("Description").''; print ''.$langs->trans("QtyOrdered").''; print ''.$langs->trans("QtyShipped").''; - print ''.$langs->trans("QtyToShip").''; + print ''.$langs->trans("QtyToShip").''; if ($conf->stock->enabled) { - if ($_GET["entrepot_id"]) - { - print ''.$langs->trans("Stock").''; - } - else - { - print ''.$langs->trans("Warehouse").''; - } + print ''.$langs->trans("Warehouse").' / '.$langs->trans("Stock").''; } print "\n"; } + $product_static = new Product($db); + $var=true; $indiceAsked = 0; while ($indiceAsked < $numAsked) @@ -484,37 +482,63 @@ if ($_GET["action"] == 'create') $line = $object->lines[$indiceAsked]; $var=!$var; + + // Show product and description + $type=$line->product_type?$line->product_type:$line->fk_product_type; + // Try to enhance type detection using date_start and date_end for free lines where type + // was not saved. + if (! empty($line->date_start)) $type=1; + if (! empty($line->date_end)) $type=1; + print "\n"; - // Desc + // Product label if ($line->fk_product > 0) { $product->fetch($line->fk_product); + $product->load_stock(); print ''; - print ''; - if ($line->product_type == 1) + print ''; // ancre pour retourner sur la ligne + + // Show product and description + $product_static->type=$line->fk_product_type; + $product_static->id=$line->fk_product; + $product_static->ref=$line->ref; + $product_static->libelle=$line->product_label; + $text=$product_static->getNomUrl(1); + $text.= ' - '.$line->product_label; + $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($line->desc)); + print $html->textwithtooltip($text,$description,3,'','',$i); + + // Show range + print_date_range($db->jdate($line->date_start),$db->jdate($line->date_end)); + + // Add description in form + if ($conf->global->PRODUIT_DESC_IN_FORM) { - print img_object($langs->trans("ShowService"),"service"); + print ($line->desc && $line->desc!=$line->product_label)?'
'.dol_htmlentitiesbr($line->desc):''; } - else - { - print img_object($langs->trans("ShowProduct"),"product"); - } - print ' '.$product->ref.' - '.$product->libelle; - if ($line->desc) print '
'.dol_nl2br(dol_htmlcleanlastbr($line->desc),1); + print ''; } else - { //var_dump($ligne); - print "".nl2br($line->desc)."\n"; + { + print ""; + if ($type==1) $text = img_object($langs->trans('Service'),'service'); + else $text = img_object($langs->trans('Product'),'product'); + print $text.' '.nl2br($line->desc); + + // Show range + print_date_range($db->jdate($line->date_start),$db->jdate($line->date_end)); + print "\n"; } // Qty print ''.$line->qty.''; $qtyProdCom=$line->qty; - // Sendings + // Qty already sent print ''; $quantityDelivered = $object->expeditions[$line->id]; print $quantityDelivered; @@ -523,81 +547,58 @@ if ($_GET["action"] == 'create') $quantityAsked = $line->qty; $quantityToBeDelivered = $quantityAsked - $quantityDelivered; - if ($conf->stock->enabled && $line->product_type == 0) + if ($conf->stock->enabled + //&& $line->product_type == 0 + ) { $defaultqty=0; - if ($_GET["entrepot_id"]) + if ($_REQUEST["entrepot_id"]) { - $stock = $product->stock_entrepot[$_GET["entrepot_id"]]; + //var_dump($product); + $stock = $product->stock_entrepot[$_REQUEST["entrepot_id"]]; $stock+=0; // Convertit en numerique $defaultqty=min($quantityToBeDelivered, $stock); - if ($defaultqty < 0) $defaultqty=0; + if ($line->product_type == 1 || $defaultqty < 0) $defaultqty=0; } // Quantity - print ''; + print ''; print ''; - print ''; + print ''; + if ($line->product_type == 1) print ' ('.$langs->trans("Service").')'; print ''; // Stock - if ($_GET["entrepot_id"]) + if ($conf->stock->enabled) { - print ''; - print $stock; - if ($stock < $quantityToBeDelivered) + if ($_REQUEST["entrepot_id"]) { - print ' '.img_warning($langs->trans("StockTooLow")); - } - print ''; - } - else - { - $array=array(); - - $sql = "SELECT e.rowid, e.label, ps.reel"; - $sql.= " FROM ".MAIN_DB_PREFIX."product_stock as ps"; - $sql.= ", ".MAIN_DB_PREFIX."entrepot as e"; - $sql.= " WHERE ps.fk_entrepot = e.rowid"; - $sql.= " AND fk_product = '".$product->id."'"; - - $result = $db->query($sql) ; - if ($result) - { - $num = $db->num_rows($result); - $i=0; - if ($num > 0) + print ''; + $formproduct->selectWarehouses($_REQUEST["entrepot_id"],'entl'.$indiceAsked,'',1,0,$line->fk_product); + //print $stock; + if ($stock < $quantityToBeDelivered) { - while ($i < $num) - { - $obj = $db->fetch_object($result); - $array[$obj->rowid] = $obj->label.' ('.$obj->reel.')'; - $i++; - } + print ' '.img_warning($langs->trans("StockTooLow")); } - $db->free($result); + print ''; } else { - $this->error=$db->error(); - return -1; + print ''; + $formproduct->selectWarehouses('','entl'.$indiceAsked,'',1,0,$line->fk_product); + print ''; } - - print ''; - $html->select_array('entl'.$i,$array,'',1,0,0); - print ''; } - } - else + /*else { // Quantity print ''; print ''; - print ''; + print ''; print ''; if ($line->product_type == 1) print ' '; - } + }*/ print "\n"; diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index 424cff2e5a9..95c2b82b042 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -438,6 +438,8 @@ if ($id > 0 || ! empty($ref)) if (! empty($objp->date_end)) $type=1; print ""; + + // Product label if ($objp->fk_product > 0) { print ''; @@ -603,7 +605,7 @@ if ($id > 0 || ! empty($ref)) // Bouton expedier avec gestion des stocks - if ($conf->stock->enabled && $commande->statut > 0 && $commande->statut < 3) + if ($commande->statut > 0 && $commande->statut < 3) { if ($user->rights->expedition->creer) { @@ -616,18 +618,22 @@ if ($id > 0 || ! empty($ref)) print ''; print ''; - $entrepot = new Entrepot($db); $langs->load("stocks"); print ''; - print ''; - print ''; + print ''; } - print '\n"; if ($ligne->fk_product > 0) { - $product = new Product($db); $product->fetch($ligne->fk_product); + $product->load_stock(); print '
'.$langs->trans("WarehouseSource").''; - $result=$formproduct->selectWarehouses(-1,'entrepot_id','',1); - if ($result <= 0) + + if ($conf->stock->enabled) { - print '   No warehouse defined, add one'; + print ''.$langs->trans("WarehouseSource").''; + $result=$formproduct->selectWarehouses(-1,'entrepot_id','',1); + if ($result <= 0) + { + print '   No warehouse defined, add one'; + } + print ''; + print ''; print ''; if ($reste_a_livrer_total <= 0) { diff --git a/htdocs/langs/ca_ES/stocks.lang b/htdocs/langs/ca_ES/stocks.lang index aa98012d721..dce42e053ad 100644 --- a/htdocs/langs/ca_ES/stocks.lang +++ b/htdocs/langs/ca_ES/stocks.lang @@ -45,7 +45,7 @@ RuleForStockManagementDecrease=Regla de gestió de decrements d'estoc RuleForStockManagementIncrease=Regla de gestió d'increments d'estoc DeStockOnBill=Decrementar els estocs físics sobre les factures/abonaments a clients (atenció, en aquesta versió, encara es fa l'ajustament sobre el magatzem número 1) DeStockOnValidateOrder=Decrementar els estocs físics sobre les comandes de clients (atenció, en aquesta versió, encara es fa l'ajustament sobre el magatzem número 1) -DeStockOnShipment=Decrementar els estocs físics sobre els enviaments (recomanat) +DeStockOnShipment=Decrementar els estocs físics sobre els enviaments ReStockOnBill=Incrementar els estocs físics sobre les factures/abonaments de proveïdors (atenció, en aquesta versió, encara es fa l'ajustament sobre el magatzem número 1) ReStockOnValidateOrder=Incrementar els estocs físics sobre les comandes a proveïdors (atenció, en aquesta versió, encara es fa l'ajustament sobre el magatzem número 1) ReStockOnDispatchOrder=Incrementa els estocs físics en el desglossament manual de la recepció de les comandes a proveïdors en els magatzems diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index aef2c5581ea..03314e9e959 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -45,7 +45,7 @@ RuleForStockManagementDecrease=Rule for stock management decrease RuleForStockManagementIncrease=Rule for stock management increase DeStockOnBill=Decrease real stocks on customers invoices/credit notes validation (warning, in this version, it's only in warehouse number 1 that stock is modified) DeStockOnValidateOrder=Decrease real stocks on customers orders validation (warning, in this version, it's only in warehouse number 1 that stock is modified) -DeStockOnShipment=Decrease real stocks on shipment validation (recommended) +DeStockOnShipment=Decrease real stocks on shipment validation ReStockOnBill=Increase real stocks on suppliers invoices/credit notes validation (warning, in this version, it's only in warehouse number 1 that stock is modified) ReStockOnValidateOrder=Increase real stocks on suppliers orders approbation (warning, in this version, it's only in warehouse number 1 that stock is modified) ReStockOnDispatchOrder=Increase real stocks on manual dispatching into warehouses, after supplier order receiving diff --git a/htdocs/langs/es_ES/stocks.lang b/htdocs/langs/es_ES/stocks.lang index b6b4a01763c..432309f5d00 100644 --- a/htdocs/langs/es_ES/stocks.lang +++ b/htdocs/langs/es_ES/stocks.lang @@ -45,7 +45,7 @@ RuleForStockManagementDecrease=Regla de gestión de decrementos de stock RuleForStockManagementIncrease=Regla de gestión de incrementos de stock DeStockOnBill=Decrementar los stocks físicos sobre las facturas/abonos a clientes (atención, en esta versión, todavía se realiza el ajuste sobre el almacén número 1) DeStockOnValidateOrder=Decrementar los stocks físicos sobre los pedidos de clientes (atención, en esta versión, todavía se realiza el ajuste sobre el almacén número 1) -DeStockOnShipment=Decrementar los stocks físicos sobre los envíos (recomendado) +DeStockOnShipment=Decrementar los stocks físicos sobre los envíos ReStockOnBill=Incrementar los stocks físicos sobre las facturas/abonos de proveedores (atención, en esta versión, todavía se realiza el ajuste sobre el almacén número 1) ReStockOnValidateOrder=Incrementar los stocks físicos sobre los pedidos a proveedores (atención, en esta versión, todavía se realiza el ajuste sobre el almacén número 1) ReStockOnDispatchOrder=Incrementa los stocks físicos en el desglose manual de la recepción de los pedidos a proveedores en los almacenes diff --git a/htdocs/langs/fr_FR/stocks.lang b/htdocs/langs/fr_FR/stocks.lang index 7ab9e042a96..63c15c9cc95 100644 --- a/htdocs/langs/fr_FR/stocks.lang +++ b/htdocs/langs/fr_FR/stocks.lang @@ -45,7 +45,7 @@ RuleForStockManagementDecrease=Règle de gestion des décrémentations de stock RuleForStockManagementIncrease=Règle de gestion des incrémentations de stock DeStockOnBill=Décrémente les stocks physiques sur validation des factures/avoirs clients (attention, dans cette version, c'est toujours dans le premier entrepôt que se fait l'ajustement) DeStockOnValidateOrder=Décrémente les stocks physiques sur validation des commandes clients (attention, dans cette version, c'est toujours dans le premier entrepôt que se fait l'ajustement) -DeStockOnShipment=Décrémente les stocks physiques sur validation des expéditions (recommandé) +DeStockOnShipment=Décrémente les stocks physiques sur validation des expéditions ReStockOnBill=Incrémente les stocks physiques sur validation des factures/avoirs fournisseurs (attention, dans cette version, c'est toujours dans le premier entrepôt que se fait l'ajustement) ReStockOnValidateOrder=Incrémente les stocks physiques sur approbations des commandes fournisseurs (attention, dans cette version, c'est toujours dans le premier entrepôt que se fait l'ajustement) ReStockOnDispatchOrder=Incrémente les stocks physiques sur ventilation manuelle de la réception des commandes fournisseurs dans les entrepôts diff --git a/htdocs/livraison/class/livraison.class.php b/htdocs/livraison/class/livraison.class.php index b836fbbd493..6b2d5c1251b 100644 --- a/htdocs/livraison/class/livraison.class.php +++ b/htdocs/livraison/class/livraison.class.php @@ -374,7 +374,7 @@ class Livraison extends CommonObject if ($resql) { // Si module stock gere et que expedition faite depuis un entrepot - if (!$conf->expedition->enabled && $conf->stock->enabled && $this->entrepot_id && $conf->global->STOCK_CALCULATE_ON_SHIPMENT == 1) + if ($conf->stock->enabled && $this->entrepot_id && $conf->global->STOCK_CALCULATE_ON_RECEIVING == 1) { //Enregistrement d'un mouvement de stock pour chaque produit de l'expedition @@ -399,14 +399,9 @@ class Livraison extends CommonObject $obj = $this->db->fetch_object($resql); $mouvS = new MouvementStock($this->db); - $result=$mouvS->livraison($user, $obj->fk_product, $this->entrepot_id, $obj->qty, $obj->subprice); - if ($result < 0) - { - $this->db->rollback(); - $this->error=$this->db->error()." - sql=$sql"; - dol_syslog("livraison.class.php::valid ".$this->error, LOG_ERR); - return -3; - } + $entrepot_id = "1"; // TODO ajouter possibilite de choisir l'entrepot + $result=$mouvS->livraison($user, $obj->fk_product, $entrepot_id, $obj->qty, $obj->subprice); + if ($result < 0) { $error++; break; } $i++; } diff --git a/htdocs/livraison/fiche.php b/htdocs/livraison/fiche.php index ffa036457f5..45bbbc17aaa 100644 --- a/htdocs/livraison/fiche.php +++ b/htdocs/livraison/fiche.php @@ -297,13 +297,15 @@ if ($_GET["action"] == 'create') $var=true; while ($i < $num) { + $product = new Product($db); + $ligne = $commande->lignes[$i]; $var=!$var; print "
'; print ''.img_object($langs->trans("ShowProduct"),"product").' '.$product->ref.' - '.$product->libelle; diff --git a/htdocs/product/class/html.formproduct.class.php b/htdocs/product/class/html.formproduct.class.php index 150515cacc8..34655b56350 100644 --- a/htdocs/product/class/html.formproduct.class.php +++ b/htdocs/product/class/html.formproduct.class.php @@ -54,17 +54,26 @@ class FormProduct /** * \brief Load in cache array list of warehouses - * \return int Nb of loaded lines, 0 if already loaded, <0 if KO + * \param fk_product Add quantity of stock in label for product with id fk_product. Nothing if 0. + * \return int Nb of loaded lines, 0 if already loaded, <0 if KO + * \remarks If fk_product is not 0, we do not use cache */ - function loadWarehouses() + function loadWarehouses($fk_product=0) { global $langs; - if (sizeof($this->cache_warehouses)) return 0; // Cache already loaded + if (empty($fk_product) && sizeof($this->cache_warehouses)) return 0; // Cache already loaded and we do not want a list with information specific to a product - $sql = "SELECT e.rowid, e.label FROM ".MAIN_DB_PREFIX."entrepot as e"; - $sql .= " WHERE statut = 1"; - $sql .= " ORDER BY e.label"; + $sql = "SELECT e.rowid, e.label"; + if ($fk_product) $sql.= ", ps.reel"; + $sql.= " FROM ".MAIN_DB_PREFIX."entrepot as e"; + if ($fk_product) + { + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps on ps.fk_entrepot = e.rowid"; + $sql.= " AND ps.fk_product = '".$fk_product."'"; + } + $sql.= " WHERE statut = 1"; + $sql.= " ORDER BY e.label"; dol_syslog('FormProduct::loadWarehouses sql='.$sql,LOG_DEBUG); $resql = $this->db->query($sql); @@ -78,6 +87,7 @@ class FormProduct $this->cache_warehouses[$obj->rowid]['id'] =$obj->rowid; $this->cache_warehouses[$obj->rowid]['label']=$obj->label; + if ($fk_product) $this->cache_warehouses[$obj->rowid]['stock']=$obj->reel; $i++; } return $num; @@ -96,15 +106,16 @@ class FormProduct * \param filtertype For filtre * \param empty 1=Can be empty, 0 if not * \param disabled 1=Select is disabled + * \param fk_product Add quantity of stock in label for product with id fk_product. Nothing if 0. * \return int <0 if KO, Nb of product in list if OK */ - function selectWarehouses($selected='',$htmlname='idwarehouse',$filtertype='',$empty=0,$disabled=0) + function selectWarehouses($selected='',$htmlname='idwarehouse',$filtertype='',$empty=0,$disabled=0,$fk_product=0) { global $langs,$user; - dol_syslog("Form::selectWarehouses $selected, $htmlname, $filtertype, $format",LOG_DEBUG); + dol_syslog("Form::selectWarehouses $selected, $htmlname, $filtertype, $empty, $disabled, $fk_product",LOG_DEBUG); - $this->loadWarehouses(); + $this->loadWarehouses($fk_product); print ''; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 0e88c8c2bb2..4ab25c391da 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2348,7 +2348,7 @@ class Product extends CommonObject $i=0; if ($num > 0) { - while ($i < $num ) + while ($i < $num) { $row = $this->db->fetch_row($result); $this->stock_entrepot[$row[1]] = $row[0];