From d1a90768cd436c95645a669f5d0b36a0f0131d01 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 23 Oct 2008 21:54:30 +0000 Subject: [PATCH] Fix: Maxi debug on stock decrease --- htdocs/admin/stock.php | 144 ++-- htdocs/commande/commande.class.php | 239 +++--- htdocs/commande/liste.php | 65 +- htdocs/expedition/commande.php | 41 +- htdocs/expedition/fiche.php | 23 +- htdocs/langs/en_US/products.lang | 2 +- htdocs/langs/en_US/sendings.lang | 5 +- htdocs/langs/en_US/stocks.lang | 3 +- htdocs/langs/es_ES/products.lang | 2 +- htdocs/langs/fr_BE/products.lang | 2 +- htdocs/langs/fr_FR/orders.lang | 2 +- htdocs/langs/fr_FR/products.lang | 2 +- htdocs/langs/fr_FR/sendings.lang | 5 +- htdocs/langs/fr_FR/stocks.lang | 3 +- htdocs/langs/it_IT/stocks.lang | 2 +- htdocs/product.class.php | 165 ++-- htdocs/product/sousproduits/fiche.php | 456 ++++++----- htdocs/product/stock/mouvementstock.class.php | 738 +++++++++--------- htdocs/product/stock/product.php | 17 +- 19 files changed, 1027 insertions(+), 889 deletions(-) diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index 5b43a9b120a..1f261b1a1a8 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -19,10 +19,10 @@ /** \file htdocs/admin/stock.php - \ingroup stock - \brief Page d'administration/configuration du module gestion de stock - \version $Id$ -*/ + \ingroup stock + \brief Page d'administration/configuration du module gestion de stock + \version $Id$ + */ require("./pre.inc.php"); require_once(DOL_DOCUMENT_ROOT."/lib/admin.lib.php"); @@ -30,32 +30,32 @@ $langs->load("admin"); $langs->load("stocks"); if (!$user->admin) - accessforbidden(); +accessforbidden(); /* -* Actions -*/ + * Actions + */ if ($_POST["action"] == 'stock_userstock') { - dolibarr_set_const($db, "STOCK_USERSTOCK", $_POST["stock_userstock"]); - //On d�sactive l'autocr�ation si l'option "stock personnel" est d�sactiv�e - if ($_POST["stock_userstock"] == 0) - { - dolibarr_set_const($db, "STOCK_USERSTOCK_AUTOCREATE", 0); - } - Header("Location: stock.php"); - exit; + dolibarr_set_const($db, "STOCK_USERSTOCK", $_POST["stock_userstock"]); + //On d�sactive l'autocr�ation si l'option "stock personnel" est d�sactiv�e + if ($_POST["stock_userstock"] == 0) + { + dolibarr_set_const($db, "STOCK_USERSTOCK_AUTOCREATE", 0); + } + Header("Location: stock.php"); + exit; } elseif ($_POST["action"] == 'stock_userstock_autocreate') { - dolibarr_set_const($db, "STOCK_USERSTOCK_AUTOCREATE", $_POST["stock_userstock_autocreate"]); - Header("Location: stock.php"); - exit; + dolibarr_set_const($db, "STOCK_USERSTOCK_AUTOCREATE", $_POST["stock_userstock_autocreate"]); + Header("Location: stock.php"); + exit; } -// Mode of stock changement +// Mode of stock changement elseif ( $_POST["action"] == 'stock_bill' - || $_POST["action"] == 'stock_validateorder' - || $_POST["action"] == 'stock_shipment') +|| $_POST["action"] == 'stock_validateorder' +|| $_POST["action"] == 'stock_shipment') { $count=0; $db->begin(); @@ -68,15 +68,15 @@ elseif ( $_POST["action"] == 'stock_bill' if ($count == 4) { $db->commit(); - Header("Location: stock.php"); - exit; + Header("Location: stock.php"); + exit; } else - { + { $db->rollback(); - dolibarr_print_error("Error in some requests", LOG_ERR); + dolibarr_print_error("Error in some requests", LOG_ERR); } -} +} @@ -116,25 +116,26 @@ print "\n\n\n"; if ($conf->global->STOCK_USERSTOCK == 1) { - $var=!$var; + $var=!$var; - print ""; - print ''.$langs->trans("UserWarehouseAutoCreate").''; - - print ''; - print "
"; - print ""; - print $html->selectyesno("stock_userstock_autocreate",$conf->global->STOCK_USERSTOCK_AUTOCREATE,1); - - print ''; - print '
'; - print "\n"; - print "\n"; + print ""; + print ''.$langs->trans("UserWarehouseAutoCreate").''; + + print ''; + print "
"; + print ""; + print $html->selectyesno("stock_userstock_autocreate",$conf->global->STOCK_USERSTOCK_AUTOCREATE,1); + + print ''; + print '
'; + print "\n"; + print "\n"; } +// Title rule for stock decrease print ''; -print " ".$langs->trans("RuleForStockManagement")."\n"; +print " ".$langs->trans("RuleForStockManagementDecrease")."\n"; print " ".$langs->trans("Value")."\n"; print ''."\n"; $var=true; @@ -142,42 +143,57 @@ $var=true; if ($conf->facture->enabled) { $var=!$var; - print ""; - print ''.$langs->trans("DeStockReStockOnBill").''; - print ''; - print "
"; - print ""; - print $html->selectyesno("stock_bill",$conf->global->STOCK_CALCULATE_ON_BILL,1); - print ''; - print "
\n\n\n"; + print ""; + print ''.$langs->trans("DeStockReStockOnBill").''; + print ''; + print "
"; + print ""; + print $html->selectyesno("stock_bill",$conf->global->STOCK_CALCULATE_ON_BILL,1); + print ''; + print "
\n\n\n"; } if ($conf->commande->enabled) { $var=!$var; - print ""; - print ''.$langs->trans("DeStockReStockOnValidateOrder").''; - print ''; - print "
"; - print ""; - print $html->selectyesno("stock_validateorder",$conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER,1); - print ''; - print "
\n\n\n"; + print ""; + print ''.$langs->trans("DeStockReStockOnValidateOrder").''; + print ''; + print "
"; + print ""; + print $html->selectyesno("stock_validateorder",$conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER,1); + print ''; + print "
\n\n\n"; } if ($conf->expedition->enabled) { $var=!$var; - print ""; - print ''.$langs->trans("DeStockReStockOnShipment").''; - print ''; - print "
"; - print ""; - print $html->selectyesno("stock_shipment",$conf->global->STOCK_CALCULATE_ON_SHIPMENT,1); - print ''; - print "
\n\n\n"; + print ""; + print ''.$langs->trans("DeStockReStockOnShipment").''; + print ''; + print "
"; + print ""; + print $html->selectyesno("stock_shipment",$conf->global->STOCK_CALCULATE_ON_SHIPMENT,1); + print ''; + print "
\n\n\n"; } + +// Title rule for stock increase +print ''; +print " ".$langs->trans("RuleForStockManagementIncrease")."\n"; +print " ".$langs->trans("Value")."\n"; +print ''."\n"; +$var=true; + + +$var=!$var; +print ""; +print ''.$langs->trans("FeatureNotYetAvailable").''; +print ''."\n"; + + print ''; $db->close(); diff --git a/htdocs/commande/commande.class.php b/htdocs/commande/commande.class.php index b93e67798c6..7d8ce57d6c2 100644 --- a/htdocs/commande/commande.class.php +++ b/htdocs/commande/commande.class.php @@ -52,7 +52,7 @@ class Commande extends CommonObject var $ref_client; var $contactid; var $projet_id; - var $statut; // -1=Annulee, 0=Brouillon, 1=Validee, 2=Acceptee, 3=Recue (facturee ou non) + var $statut; // -1=Annulee, 0=Brouillon, 1=Validee, 2=Acceptee, 3=Envoyee/Recue (facturee ou non) var $facturee; var $brouillon; var $cond_reglement_id; @@ -205,6 +205,7 @@ class Commande extends CommonObject { global $conf,$langs; + // Protection if ($this->statut == 1) { return 0; @@ -212,7 +213,7 @@ class Commande extends CommonObject if (! $user->rights->commande->valider) { - $this->error='Autorisation insuffisante'; + $this->error='Permission denied'; return -1; } @@ -274,31 +275,15 @@ class Commande extends CommonObject } } - //Si active on decremente le produit principal et ses composants a la validation de command + // If stock is incremented on validate order, we must increment it if($conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER == 1) { require_once(DOL_DOCUMENT_ROOT."/product/stock/mouvementstock.class.php"); for ($i = 0 ; $i < sizeof($this->lignes) ; $i++) { - if ($conf->global->PRODUIT_SOUSPRODUITS == 1) - { - $prod = new Product($this->db, $this->lignes[$i]->fk_product); - $prod -> get_sousproduits_arbo (); - $prods_arbo = $prod->get_each_prod(); - if(sizeof($prods_arbo) > 0) - { - foreach($prods_arbo as $key => $value) - { - // on decompte le stock de tous les sousproduits - $mouvS = new MouvementStock($this->db); - $entrepot_id = "1"; //Todo: ajouter possibilite de choisir l'entrepot - $result=$mouvS->livraison($user, $value[1], $entrepot_id, $value[0]*$this->lignes[$i]->qty); - } - } - } $mouvP = new MouvementStock($this->db); - // on decompte le stock du produit principal + // We decrement stock of product (and sub-products) $entrepot_id = "1"; //Todo: ajouter possibilite de choisir l'entrepot $result=$mouvP->livraison($user, $this->lignes[$i]->fk_product, $entrepot_id, $this->lignes[$i]->qty); } @@ -325,152 +310,150 @@ class Commande extends CommonObject /** * \brief Set draft status * \param user Object user that modify - * \param int <0 if KO, >0 if OK + * \return int <0 if KO, >0 if OK */ function set_draft($user) { global $conf,$langs; + // Protection + if ($this->statut <= 0) + { + return 0; + } + + if (! $user->rights->commande->valider) + { + $this->error='Permission denied'; + return -1; + } + + $this->db->begin(); + $sql = "UPDATE ".MAIN_DB_PREFIX."commande SET fk_statut = 0"; $sql .= " WHERE rowid = ".$this->id; + dolibarr_syslog("Commande::set_draft sql=".$sql, LOG_DEBUG); if ($this->db->query($sql)) { - //Si active on incremente le produit principal et ses composants a l'edition de la commande - if($conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER == 1) - { - require_once(DOL_DOCUMENT_ROOT."/product/stock/mouvementstock.class.php"); + // If stock is decremented on validate order, we must reincrement it + if ($conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER == 1) + { + require_once(DOL_DOCUMENT_ROOT."/product/stock/mouvementstock.class.php"); for ($i = 0 ; $i < sizeof($this->lignes) ; $i++) { - if ($conf->global->PRODUIT_SOUSPRODUITS == 1) - { - $prod = new Product($this->db, $this->lignes[$i]->fk_product); - $prod -> get_sousproduits_arbo (); - $prods_arbo = $prod->get_each_prod(); - if(sizeof($prods_arbo) > 0) - { - foreach($prods_arbo as $key => $value) - { - // on decompte le stock de tous les sousproduits - $mouvS = new MouvementStock($this->db); - $entrepot_id = "1"; //Todo: ajouter possibilite de choisir l'entrepot - $result=$mouvS->reception($user, $value[1], $entrepot_id, $value[0]*$this->lignes[$i]->qty); - } - } - } $mouvP = new MouvementStock($this->db); - // on decompte le stock du produit principal + // We increment stock of product (and sub-products) $entrepot_id = "1"; //Todo: ajouter possibilite de choisir l'entrepot $result=$mouvP->reception($user, $this->lignes[$i]->fk_product, $entrepot_id, $this->lignes[$i]->qty); - } - } - return 1; + } + + if ($result > 0) + { + $this->statut=0; + $this->db->commit(); + return $result; + } + else + { + $this->error=$mouvP->error; + $this->db->rollback(); + return $result; + } + } + + $this->statut=0; + $this->db->commit(); + return 1; } else { - dolibarr_print_error($this->db); + $this->error=$this->db->error(); + $this->db->rollback(); + dolibarr_syslog($this->error, LOG_ERR); + return -1; } } /** - * \brief Cloture la commande - * \param user Objet utilisateur qui cloture - * \return int <0 si ko, >0 si ok + * \brief Cloture la commande + * \param user Objet utilisateur qui cloture + * \return int <0 if KO, >0 if OK */ function cloture($user) { global $conf; + if ($user->rights->commande->valider) { $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande'; $sql.= ' SET fk_statut = 3,'; $sql.= ' fk_user_cloture = '.$user->id.','; - $sql.= " date_cloture = ".$this->db->idate(mktime()); - $sql.= " WHERE rowid = $this->id AND fk_statut > 0 ;"; + $sql.= ' date_cloture = '.$this->db->idate(mktime()); + $sql.= ' WHERE rowid = '.$this->id.' AND fk_statut > 0'; if ($this->db->query($sql)) { - if($conf->stock->enabled && $conf->global->PRODUIT_SOUSPRODUITS == 1 && $conf->global->STOCK_CALCULATE_ON_SHIPMENT == 1) - { - require_once(DOL_DOCUMENT_ROOT."/product/stock/mouvementstock.class.php"); - for ($i = 0 ; $i < sizeof($this->lignes) ; $i++) - { - $prod = new Product($this->db, $this->lignes[$i]->fk_product); - $prod -> get_sousproduits_arbo (); - $prods_arbo = $prod->get_each_prod(); - if(sizeof($prods_arbo) > 0) - { - foreach($prods_arbo as $key => $value) - { - // on decompte le stock de tous les sousproduits - $mouvS = new MouvementStock($this->db); - $entrepot_id = "1"; - $result=$mouvS->livraison($user, $value[1], $entrepot_id, $value[0]*$this->lignes[$i]->qty); - } - } - // on decompte pas le stock du produit principal, ca serait fait manuellement avec l'expedition - // $result=$mouvS->livraison($user, $this->lignes[$i]->fk_product, $entrepot_id, $this->lignes[$i]->qty); - } - } return 1; } else { - dolibarr_print_error($this->db); + $this->error=$this->db->error(); + dolibarr_syslog($this->error, LOG_ERR); return -1; } } } /** - * Annule la commande - * + * \brief Cancel an order + * \return int <0 if KO, >0 if OK + * \remarks If stock is decremented on order validation, we must reincrement it */ function cancel($user) { global $conf; + if ($user->rights->commande->valider) { + $this->db->begin(); + $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande SET fk_statut = -1'; $sql .= " WHERE rowid = $this->id AND fk_statut = 1 ;"; if ($this->db->query($sql) ) { - //Si active on incremente le produit principal et ses composants a l'edition de la commande + // If stock is decremented on validate order, we must reincrement it if($conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER == 1) { - require_once(DOL_DOCUMENT_ROOT."/product/stock/mouvementstock.class.php"); - - for ($i = 0 ; $i < sizeof($this->lignes) ; $i++) + $mouvP = new MouvementStock($this->db); + // We increment stock of product (and sub-products) + $entrepot_id = "1"; //Todo: ajouter possibilite de choisir l'entrepot + $result=$mouvP->reception($user, $this->lignes[$i]->fk_product, $entrepot_id, $this->lignes[$i]->qty); + + if ($result > 0) { - if ($conf->global->PRODUIT_SOUSPRODUITS == 1) - { - $prod = new Product($this->db, $this->lignes[$i]->fk_product); - $prod -> get_sousproduits_arbo (); - $prods_arbo = $prod->get_each_prod(); - if(sizeof($prods_arbo) > 0) - { - foreach($prods_arbo as $key => $value) - { - // on decompte le stock de tous les sousproduits - $mouvS = new MouvementStock($this->db); - $entrepot_id = "1"; //Todo: ajouter possibilite de choisir l'entrepot - $result=$mouvS->reception($user, $value[1], $entrepot_id, $value[0]*$this->lignes[$i]->qty); - } - } - } - $mouvP = new MouvementStock($this->db); - // on decompte le stock du produit principal - $entrepot_id = "1"; //Todo: ajouter possibilite de choisir l'entrepot - $result=$mouvP->reception($user, $this->lignes[$i]->fk_product, $entrepot_id, $this->lignes[$i]->qty); + $this->db->commit(); + return $result; + } + else + { + $this->error=$mouvP->error; + $this->db->rollback(); + return $result; } } + + $this->db->commit(); return 1; } else { - dolibarr_print_error($this->db); + $this->error=$this->db->error(); + $this->db->rollback(); + dolibarr_syslog($this->error, LOG_ERR); + return -1; } } } @@ -669,7 +652,7 @@ class Commande extends CommonObject if ($this->statut == 0) { $this->db->begin(); - + // Calcul du total TTC et de la TVA pour la ligne a partir de // qty, pu, remise_percent et txtva // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker @@ -678,7 +661,7 @@ class Commande extends CommonObject $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; - + // \TODO A virer // Anciens indicateurs: $price, $remise (a ne plus utiliser) $price = $pu; @@ -688,10 +671,10 @@ class Commande extends CommonObject $remise = round(($pu * $remise_percent / 100), 2); $price = $pu - $remise; } - + // Insert line $ligne=new CommandeLigne($this->db); - + $ligne->fk_commande=$commandeid; $ligne->desc=$desc; $ligne->qty=$qty; @@ -705,16 +688,16 @@ class Commande extends CommonObject $ligne->total_ht=$total_ht; $ligne->total_tva=$total_tva; $ligne->total_ttc=$total_ttc; - + // \TODO Ne plus utiliser $ligne->price=$price; $ligne->remise=$remise; - + // Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) // Save the start and end date of the new line in the object $ligne->date_start=$date_start; $ligne->date_end=$date_end; - + $result=$ligne->insert(); if ($result > 0) { @@ -784,7 +767,7 @@ class Commande extends CommonObject $line->ref=$prod->ref; $line->libelle=$prod->libelle; $line->product_desc=$prod->description; - + // Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) // Save the start and end date of the line in the object if ($date_start) { $line->date_start = $date_start; } @@ -946,7 +929,7 @@ class Commande extends CommonObject $this->db->rollback(); return -5; } - + $comligne=new CommandeLigne($this->db); $comligne->fk_commande=$this->id; $comligne->fk_remise_except=$remise->id; @@ -960,11 +943,11 @@ class Commande extends CommonObject $comligne->remise_percent=0; $comligne->rang=-1; $comligne->info_bits=2; - + $comligne->total_ht = -$remise->amount_ht; $comligne->total_tva = -$remise->amount_tva; $comligne->total_ttc = -$remise->amount_ttc; - + $result=$comligne->insert(); if ($result > 0) { @@ -1053,7 +1036,7 @@ class Commande extends CommonObject $ligne->libelle = $objp->label; $ligne->product_desc = $objp->product_desc; // Description produit $ligne->fk_product_type = $objp->fk_product_type; // Produit ou service - + // Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) // Save the start and end date of the line in the object $ligne->date_start = $objp->date_start; @@ -1110,7 +1093,7 @@ class Commande extends CommonObject if ($filtre_statut >= 0) $sql.=' AND e.fk_statut = '.$filtre_statut; $sql.= ' GROUP BY cd.rowid, cd.fk_product'; //print $sql; - + dolibarr_syslog("Commande::loadExpeditions sql=".$sql,LOG_DEBUG); $result = $this->db->query($sql); if ($result) @@ -1232,11 +1215,11 @@ class Commande extends CommonObject if ($this->statut == 0) { $this->db->begin(); - + $sql = "SELECT fk_product, qty"; $sql.= " FROM ".MAIN_DB_PREFIX."commandedet"; $sql.= " WHERE rowid = '$idligne'"; - + $result = $this->db->query($sql); if ($result) { @@ -1378,7 +1361,7 @@ class Commande extends CommonObject $sql = "UPDATE ".MAIN_DB_PREFIX."commande"; $sql.= " SET date_livraison = ".($date_livraison ? $this->db->idate($date_livraison) : 'null'); $sql.= " WHERE rowid = ".$this->id." AND fk_statut = 0"; - + dolibarr_syslog("Commande::set_date_livraison sql=$sql",LOG_DEBUG); $resql=$this->db->query($sql); if ($resql) @@ -1679,14 +1662,14 @@ class Commande extends CommonObject $sql.= ",total_ht='".price2num($total_ht)."'"; $sql.= ",total_tva='".price2num($total_tva)."'"; $sql.= ",total_ttc='".price2num($total_ttc)."'"; - + // Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) // Save the start and end date in the database - if ($date_start) { $sql.= ",date_start='".$date_start."'"; } - else { $sql.=',date_start=null'; } - if ($date_end) { $sql.= ",date_end='".$date_end."'"; } - else { $sql.=',date_end=null'; } - + if ($date_start) { $sql.= ",date_start='".$date_start."'"; } + else { $sql.=',date_start=null'; } + if ($date_end) { $sql.= ",date_end='".$date_end."'"; } + else { $sql.=',date_end=null'; } + $sql.= " WHERE rowid = ".$rowid; $result = $this->db->query($sql); @@ -2173,7 +2156,7 @@ class CommandeLigne var $ref; // Reference produit var $product_libelle; // Label produit var $product_desc; // Description produit - + // Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) // Start and end date of the line var $date_start; @@ -2227,16 +2210,16 @@ class CommandeLigne $this->marge_tx = $objp->marge_tx; $this->marque_tx = $objp->marque_tx; $this->rang = $objp->rang; - + $this->ref = $objp->product_ref; $this->product_libelle = $objp->product_libelle; $this->product_desc = $objp->product_desc; - + // Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) // Save the start and end dates of the line in the object $this->date_start = $objp->date_start; $this->date_end = $objp->date_end; - + $this->db->free($result); } else @@ -2368,7 +2351,7 @@ class CommandeLigne if ($result < 0) { $error++; $this->errors=$interface->errors; } // Fin appel triggers } - + $this->db->commit(); return $this->rowid; } diff --git a/htdocs/commande/liste.php b/htdocs/commande/liste.php index d875ab906f1..aa8a5c5af53 100644 --- a/htdocs/commande/liste.php +++ b/htdocs/commande/liste.php @@ -20,11 +20,11 @@ */ /** - \file htdocs/commande/liste.php - \ingroup commande - \brief Page liste des commandes - \version $Id$ -*/ + \file htdocs/commande/liste.php + \ingroup commande + \brief Page liste des commandes + \version $Id$ + */ require('./pre.inc.php'); @@ -50,10 +50,10 @@ $result = restrictedArea($user, 'commande', $orderid,''); /* * View */ - + $html = new Form($db); $formfile = new FormFile($db); - + llxHeader(); $begin=$_GET['begin']; @@ -75,7 +75,7 @@ if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFI $sql.= ' WHERE c.fk_soc = s.rowid'; if (!$user->rights->societe->client->voir && !$socid) //restriction { - $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; + $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; } if ($sref) { @@ -147,20 +147,20 @@ if ($resql) $title = $langs->trans('ListOfOrders'); } if (strval($_GET['viewstatut']) == '0') - $title.=' - '.$langs->trans('StatusOrderDraftShort'); + $title.=' - '.$langs->trans('StatusOrderDraftShort'); if ($_GET['viewstatut'] == 1) - $title.=' - '.$langs->trans('StatusOrderValidatedShort'); + $title.=' - '.$langs->trans('StatusOrderValidatedShort'); if ($_GET['viewstatut'] == 2) - $title.=' - '.$langs->trans('StatusOrderOnProcessShort'); + $title.=' - '.$langs->trans('StatusOrderOnProcessShort'); if ($_GET['viewstatut'] == 3) - $title.=' - '.$langs->trans('StatusOrderToBillShort'); + $title.=' - '.$langs->trans('StatusOrderToBillShort'); if ($_GET['viewstatut'] == 4) - $title.=' - '.$langs->trans('StatusOrderProcessedShort'); + $title.=' - '.$langs->trans('StatusOrderProcessedShort'); if ($_GET['viewstatut'] == -1) - $title.=' - '.$langs->trans('StatusOrderCanceledShort'); + $title.=' - '.$langs->trans('StatusOrderCanceledShort'); if ($_GET['viewstatut'] == -2) - $title.=' - '.$langs->trans('StatusOrderToProcessShort'); - + $title.=' - '.$langs->trans('StatusOrderToProcessShort'); + $num = $db->num_rows($resql); print_barre_liste($title, $_GET['page'], 'liste.php','&socid='.$socid.'&viewstatut='.$viewstatut,$sortfield,$sortorder,'',$num); $i = 0; @@ -193,39 +193,42 @@ if ($resql) $objp = $db->fetch_object($resql); $var=!$var; print ''; - print ''; - - $generic_commande->id=$objp->rowid; + print ''; + + $generic_commande->id=$objp->rowid; $generic_commande->ref=$objp->ref; - + print ''; print ''; - + print ''; - + print '
'; print $generic_commande->getNomUrl(1,$objp->fk_statut); print ''; if (($objp->fk_statut > 0) && ($objp->fk_statut < 3) && $objp->date_commande < (time() - $conf->commande->traitement->warning_delay)) print img_picto($langs->trans("Late"),"warning"); print ''; $filename=sanitize_string($objp->ref); $filedir=$conf->commande->dir_output . '/' . sanitize_string($objp->ref); $urlsource=$_SERVER['PHP_SELF'].'?id='.$objp->rowid; $formfile->show_documents('commande',$filename,$filedir,$urlsource,'','','','','',1); print '
'; - + print ''; - + print ''.img_object($langs->trans('ShowCompany'),'company').' '.$objp->nom.''; + print ''.$objp->ref_client.''; + + // Date + $y = dolibarr_print_date($objp->date_commande,'%Y'); + $m = dolibarr_print_date($objp->date_commande,'%m'); + $ml = dolibarr_print_date($objp->date_commande,'%B'); + $d = dolibarr_print_date($objp->date_commande,'%d'); print ''; - $y = strftime('%Y',$objp->date_commande); - $m = strftime('%m',$objp->date_commande); - print strftime('%d',$objp->date_commande); - print ' '; - print strftime('%B',$objp->date_commande).''; - print ' '; - print strftime('%Y',$objp->date_commande).''; + print $d; + print ' '.$ml.''; + print ' '.$y.''; print ''; print ''.$generic_commande->LibStatut($objp->fk_statut,$objp->facturee,5).''; print ''; diff --git a/htdocs/expedition/commande.php b/htdocs/expedition/commande.php index 792cdc8a9f9..608f8d82019 100644 --- a/htdocs/expedition/commande.php +++ b/htdocs/expedition/commande.php @@ -183,12 +183,12 @@ if ($_GET["id"] > 0) } print ''; print ''; - + // Société print ''.$langs->trans('Company').''; print ''.$soc->getNomUrl(1).''; print ''; - + // Date print ''.$langs->trans('Date').''; print ''.dolibarr_print_date($commande->date,'daytext').''; @@ -202,13 +202,13 @@ if ($_GET["id"] > 0) } print ''; print ''; - + // Date de livraison print ''; print ''; - + if ($_GET['action'] != 'editdate_livraison' && $commande->brouillon) print ''; print '
'; print $langs->trans('DeliveryDate'); print 'id.'">'.img_edit($langs->trans('SetDeliveryDate'),1).'
'; print ''; @@ -229,17 +229,17 @@ if ($_GET["id"] > 0) print nl2br($commande->note_public); print ''; print ''; - + // Adresse de livraison print ''; print ''; - + if ($_GET['action'] != 'editdelivery_adress' && $commande->brouillon) print ''; print '
'; print $langs->trans('DeliveryAddress'); print 'socid.'&id='.$commande->id.'">'.img_edit($langs->trans('SetDeliveryAddress'),1).'
'; print ''; - + if ($_GET['action'] == 'editdelivery_adress') { $html->form_adresse_livraison($_SERVER['PHP_SELF'].'?id='.$commande->id,$commande->adresse_livraison_id,$_GET['socid'],'adresse_livraison_id','commande',$commande->id); @@ -249,7 +249,7 @@ if ($_GET["id"] > 0) $html->form_adresse_livraison($_SERVER['PHP_SELF'].'?id='.$commande->id,$commande->adresse_livraison_id,$_GET['socid'],'none','commande',$commande->id); } print ''; - + // Conditions et modes de réglement print ''; print ''; + $qtyProdCom=$ligne->qty; print ''; } + } else { @@ -435,6 +437,17 @@ if ($_GET["action"] == 'create') print "\n"; + // associations sous produits + $product->get_sousproduits_arbo (); + $prods_arbo = $product->get_arbo_each_prod($qtyProdCom); + if(sizeof($prods_arbo) > 0) + { + foreach($prods_arbo as $key => $value) + { + print $value[0]; + } + } + $indiceAsked++; } @@ -448,7 +461,7 @@ if ($_GET["action"] == 'create') } else { - dolibarr_print_error($db); + dolibarr_print_error($db); } } } @@ -506,7 +519,7 @@ else */ if ($_GET["action"] == 'delete') { - $html->form_confirm($_SERVER['PHP_SELF'].'?id='.$expedition->id,$langs->trans('DeleteSending'),'Etes-vous sûr de vouloir supprimer cette expedition ?','confirm_delete'); + $html->form_confirm($_SERVER['PHP_SELF'].'?id='.$expedition->id,$langs->trans('DeleteSending'),$langs->trans("ConfirmDeleteSending",$expedition->ref),'confirm_delete'); print '
'; } @@ -516,7 +529,7 @@ else */ if ($_GET["action"] == 'valid') { - $html->form_confirm($_SERVER['PHP_SELF'].'?id='.$expedition->id,$langs->trans('ValidateSending'),'Etes-vous sûr de vouloir valider cette expédition ?','confirm_valid'); + $html->form_confirm($_SERVER['PHP_SELF'].'?id='.$expedition->id,$langs->trans('ValidateSending'),$langs->trans("ConfirmValidateSending",$expedition->ref),'confirm_valid'); print '
'; } /* @@ -525,7 +538,7 @@ else */ if ($_GET["action"] == 'annuler') { - $html->form_confirm($_SERVER['PHP_SELF'].'?id='.$expedition->id,$langs->trans('CancelSending'),'Etes-vous sûr de vouloir annuler cette commande ?','confirm_cancel'); + $html->form_confirm($_SERVER['PHP_SELF'].'?id='.$expedition->id,$langs->trans('CancelSending'),$langs->trans("ConfirmCancelSending",$expedition->ref),'confirm_cancel'); print '
'; } @@ -741,7 +754,7 @@ else print '
'; //show_list_sending_receive($expedition->origin,$expedition->origin_id," AND e.rowid <> ".$expedition->id); show_list_sending_receive($expedition->origin,$expedition->origin_id); - + } else { diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index ab062af0c3f..05ea0e0d68e 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -99,7 +99,7 @@ MultiPriceLevelsName=Price categories AssociatedProductsAbility=Activate the associated products AssociatedProducts=Associated products AssociatedProductsNumber=Number of associated products -EditAssociate=Associated +EditAssociate=Associate Translation=Translation KeywordFilter=Keyword filter CategoryFilter=Category filter diff --git a/htdocs/langs/en_US/sendings.lang b/htdocs/langs/en_US/sendings.lang index 91814da1ded..10b1ecd8068 100644 --- a/htdocs/langs/en_US/sendings.lang +++ b/htdocs/langs/en_US/sendings.lang @@ -34,4 +34,7 @@ SendingSheet=Sending sheet Carriers=Carriers Carrier=Carrier CarriersArea=Carriers area -NewCarrier=New carrier \ No newline at end of file +NewCarrier=New carrier +ConfirmDeleteSending=Are you sure you want to delete this sending ? +ConfirmValidateSending=Are you sure you want to valdate this sending ? +ConfirmCancelSending=Are you sure you want to cancel this sending ? diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 9e767ed629a..c01b80ebfcf 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -38,7 +38,8 @@ EnhancedValueOfWarehouses=Warehouses value UserWarehouseAutoCreate=Create a stock automatically when creating a user QtyDispatched=Quantity dispatched OrderDispatch=Order dispatching -RuleForStockManagement=Rule for stock management +RuleForStockManagementDecrease=Rule for stock management decrease +RuleForStockManagementIncrease=Rule for stock management increase DeStockReStockOnBill=Decrease/increase real stocks on invoices/credit notes (warning, in this version, it's only in warehouse number 1 that stock is modified) DeStockReStockOnValidateOrder=Decrease/increase real stocks on orders notes (warning, in this version, it's only in warehouse number 1 that stock is modified) DeStockReStockOnShipment=Decrease/increase real stocks on shipment (recommanded) diff --git a/htdocs/langs/es_ES/products.lang b/htdocs/langs/es_ES/products.lang index ba67fe2b395..0f8af1560ff 100644 --- a/htdocs/langs/es_ES/products.lang +++ b/htdocs/langs/es_ES/products.lang @@ -100,7 +100,7 @@ MultiPriceLevelsName=Categor AssociatedProductsAbility=Activar productos asociados AssociatedProducts=Productos asociados AssociatedProductsNumber=Nº de productos asociados -EditAssociate=Asociar a +EditAssociate=Asociar Translation=Traducción KeywordFilter=Filtro por clave CategoryFilter=Filtro por categoría diff --git a/htdocs/langs/fr_BE/products.lang b/htdocs/langs/fr_BE/products.lang index 4be3c3afab9..d88dbadf42c 100644 --- a/htdocs/langs/fr_BE/products.lang +++ b/htdocs/langs/fr_BE/products.lang @@ -89,7 +89,7 @@ MultiPriceLevelsName=Cat AssociatedProductsAbility=Activer les produits associés AssociatedProducts=Produits associés AssociatedProductsNumber=Nombre de produits associés -EditAssociate=Associé +EditAssociate=Associer Translation=Traduction KeywordFilter=Filtre par mot-clé CategoryFilter=Filtre par catégorie diff --git a/htdocs/langs/fr_FR/orders.lang b/htdocs/langs/fr_FR/orders.lang index 7c9a0f8c2ce..f9f7147efc2 100755 --- a/htdocs/langs/fr_FR/orders.lang +++ b/htdocs/langs/fr_FR/orders.lang @@ -74,7 +74,7 @@ NumberOfOrdersByMonth=Nombre de commandes par mois AmountOfOrdersByMonthHT=Montant total de commandes par mois (HT) ListOfOrders=Liste des commandes CloseOrder=Cloturer commande -ConfirmCloseOrder=Êtes-vous sur de vouloir cloturer cette commande ? Une fois une commande cloturée, elle doit être facturée. +ConfirmCloseOrder=Êtes-vous sur de vouloir cloturer cette commande ? Une fois une commande cloturée, elle peut être facturée. ConfirmCloseOrderIfSending=Êtes-vous sur de vouloir cloturer cette commande ? Vous ne devez cloturer une commande qu'une fois les produits expédiés. ConfirmDeleteOrder=Êtes-vous sur de vouloir effacer cette commande ? ConfirmValidateOrder=Êtes-vous sur de vouloir valider cette commande sous la référence %s ? diff --git a/htdocs/langs/fr_FR/products.lang b/htdocs/langs/fr_FR/products.lang index 581593c4d03..94bd22b375f 100644 --- a/htdocs/langs/fr_FR/products.lang +++ b/htdocs/langs/fr_FR/products.lang @@ -103,7 +103,7 @@ MultiPriceLevelsName=Cat AssociatedProductsAbility=Prise en charges des produits associés AssociatedProducts=Produits associés AssociatedProductsNumber=Nbre de produits associés -EditAssociate=Associer au +EditAssociate=Associer Translation=Traduction KeywordFilter=Filtre par mot-clé CategoryFilter=Filtre par catégorie diff --git a/htdocs/langs/fr_FR/sendings.lang b/htdocs/langs/fr_FR/sendings.lang index bc218afa927..438e7af4e53 100644 --- a/htdocs/langs/fr_FR/sendings.lang +++ b/htdocs/langs/fr_FR/sendings.lang @@ -34,4 +34,7 @@ SendingSheet=Bordereau d'exp Carriers=Transporteurs Carrier=Transporteur CarriersArea=Espace transporteurs -NewCarrier=Nouveau transporteur \ No newline at end of file +NewCarrier=Nouveau transporteur +ConfirmDeleteSending=Etes-vous sûr de vouloir supprimer cette expedition ? +ConfirmValidateSending=Etes-vous sûr de vouloir valider cette expédition ? +ConfirmCancelSending=Etes-vous sûr de vouloir annuler cette expédition ? diff --git a/htdocs/langs/fr_FR/stocks.lang b/htdocs/langs/fr_FR/stocks.lang index 140d215395d..51a1a96b323 100644 --- a/htdocs/langs/fr_FR/stocks.lang +++ b/htdocs/langs/fr_FR/stocks.lang @@ -38,7 +38,8 @@ EnhancedValueOfWarehouses=Valorisation des stocks UserWarehouseAutoCreate=Créer un stock automatiquement à la création d'un utilisateur QtyDispatched=Quantité ventilée OrderDispatch=Ventilation commande -RuleForStockManagement=Règle de gestion de stock +RuleForStockManagementDecrease=Règle de gestion des décrémentations de stock +RuleForStockManagementIncrease=Règle de gestion des incrémentations de stock DeStockReStockOnBill=Décrémente/Incrémente les stocks physiques sur les factures/avoirs (attention, dans cette version, c'est toujours dans le premier entrepot numero 1 que se fait l'ajustement) DeStockReStockOnValidateOrder=Décrémente/Incrémente les stocks physiques sur les commandes (attention, dans cette version, c'est toujours dans le premier entrepot numero 1 que se fait l'ajustement) DeStockReStockOnShipment=Décrémente/Incrémente les stocks physiques sur les expéditions (recommandé) diff --git a/htdocs/langs/it_IT/stocks.lang b/htdocs/langs/it_IT/stocks.lang index 9040e319462..b3f25a0697f 100644 --- a/htdocs/langs/it_IT/stocks.lang +++ b/htdocs/langs/it_IT/stocks.lang @@ -38,7 +38,7 @@ EnhancedValueOfWarehouses =Valore magazzini UserWarehouseAutoCreate =Creare uno stock automaticamente durante la creazione di un utente QtyDispatched =Quantità spedita OrderDispatch =Spedizione dell'ordine -RuleForStockManagement =Regola per gestione delle scorte +RuleForStockManagementDecrease =Regola per gestione delle scorte DeStockReStockOnBill =Diminuzione / aumento reale delle scorte sulle fatture / note di credito (attenzione, in questa versione, è solo nel magazzino numero 1 che viene modificata) DeStockReStockOnValidateOrder =Diminuzione / aumento reale delle scorte per ordini note (avviso, in questa versione, è solo nel magazzino numero 1 che viene modificata) DeStockReStockOnShipment =Diminuzione / aumento reale delle scorte sulla spedizione (Raccomandato) diff --git a/htdocs/product.class.php b/htdocs/product.class.php index 67a61f8329d..6cd4305d24a 100644 --- a/htdocs/product.class.php +++ b/htdocs/product.class.php @@ -182,7 +182,7 @@ class Product extends CommonObject $price_ht = price2num($this->price,'MU'); $price_ttc = price2num($this->price * (1 + ($this->tva_tx / 100)),'MU'); } - + if (($this->price_min_ttc > 0)&&($this->price_base_type == 'TTC')) { $price_min_ttc = price2num($this->price_min_ttc,'MU'); @@ -220,13 +220,13 @@ class Product extends CommonObject $sql = "INSERT INTO ".MAIN_DB_PREFIX."product"; $sql.= " (datec, "; if ($this->ref) $sql.= "ref, "; - $sql.= "price_min, price_min_ttc, "; + $sql.= "price_min, price_min_ttc, "; $sql.= "label, "; $sql.= "fk_user_author, fk_product_type, price, price_ttc, price_base_type, canvas)"; $sql.= " VALUES (".$this->db->idate(mktime()).", "; if ($this->ref) $sql.= "'".$this->ref."',"; - $sql.= price2num($price_min_ht).","; - $sql.= price2num($price_min_ttc).","; + $sql.= price2num($price_min_ht).","; + $sql.= price2num($price_min_ttc).","; $sql.= " ".($this->libelle?"'".addslashes($this->libelle)."'":"null").","; $sql.= $user->id.","; $sql.= " ".$this->type.","; @@ -248,7 +248,7 @@ class Product extends CommonObject $this->price_ttc = $price_ttc; $this->price_min = $price_min_ht; $this->price_min_ttc = $price_min_ttc; - + $result = $this->_log_price($user); if ($result > 0) { @@ -509,7 +509,7 @@ class Product extends CommonObject $sqlb = "DELETE from ".MAIN_DB_PREFIX."product_price"; $sqlb.= " WHERE fk_product = ".$id; $resultb = $this->db->query($sqlb); - + $sqlb = "DELETE from ".MAIN_DB_PREFIX."product_price_min"; $sqlb.= " WHERE fk_product = ".$id; $resultb = $this->db->query($sqlb); @@ -699,7 +699,7 @@ class Product extends CommonObject else { $queryError = false; - + // On ajoute nouveau tarif $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_price(date_price,fk_product,fk_user_author,price,price_ttc,price_base_type,envente,tva_tx,price_min,price_min_ttc) "; $sql.= " VALUES(".$this->db->idate(mktime()).",".$this->id.",".$user->id.",".$this->price.",".$this->price_ttc.",'".$this->price_base_type."',".$this->status.",".$this->tva_tx; @@ -709,8 +709,8 @@ class Product extends CommonObject dolibarr_syslog("Product::_log_price sql=".$sql); $resql=$this->db->query($sql); if (!$resql) - $queryError = true; - + $queryError = true; + if($queryError) { dolibarr_print_error($this->db); @@ -718,8 +718,8 @@ class Product extends CommonObject } else return 1; - - + + } } @@ -825,7 +825,7 @@ class Product extends CommonObject $price_ttc = price2num($newprice,'MU'); $price = price2num($newprice) / (1 + ($newvat / 100)); $price = price2num($price,'MU'); - + if($newminprice!=''){ $price_min_ttc = price2num($newminprice,'MU'); $price_min = price2num($newminprice) / (1 + ($newvat / 100)); @@ -837,7 +837,7 @@ class Product extends CommonObject $price = price2num($newprice,'MU'); $price_ttc = price2num($newprice) * (1 + ($newvat / 100)); $price_ttc = price2num($price_ttc,'MU'); - + if($newminprice!=''){ $price_min = price2num($newminprice,'MU'); $price_min_ttc = price2num($newminprice) * (1 + ($newvat / 100)); @@ -852,7 +852,7 @@ class Product extends CommonObject $sql.= " price=".$price.","; $sql.= " price_ttc=".$price_ttc.","; $sql.= " price_min=".$price_min.","; - $sql.= " price_min_ttc=".$price_min_ttc.","; + $sql.= " price_min_ttc=".$price_min_ttc.","; $sql.= " tva_tx='".price2num($newvat)."'"; $sql.= " WHERE rowid = " . $id; @@ -1043,9 +1043,9 @@ class Product extends CommonObject } } - } + } - $res=$this->load_stock(); + $res=$this->load_stock(); return $res; } @@ -1099,7 +1099,7 @@ class Product extends CommonObject /** * \brief Charge tableau des stats commande client pour le produit/service - * \param socid Id societe pour filtrer sur une soci�t� + * \param socid Id societe pour filtrer sur une societe * \param filtrestatut Id statut pour filtrer sur un statut * \return array Tableau des stats */ @@ -1184,6 +1184,50 @@ class Product extends CommonObject } } + /** + * \brief Charge tableau des stats expedition client pour le produit/service + * \param socid Id societe pour filtrer sur une societe + * \param filtrestatut Id statut pour filtrer sur un statut + * \return array Tableau des stats + */ + function load_stats_sending($socid=0,$filtrestatut='') + { + global $conf,$user; + + $sql = "SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,"; + $sql.= " COUNT(ed.rowid) as nb_rows, SUM(ed.qty) as qty"; + $sql.= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed, ".MAIN_DB_PREFIX."commandedet as cd,"; + $sql.= " ".MAIN_DB_PREFIX."expedition as c"; + if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE c.rowid = ed.fk_expedition AND ed.fk_origin_line = cd.rowid AND cd.fk_product = ".$this->id; + 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; + } + + if ($filtrestatut <> '') + { + $sql.= " AND c.fk_statut in (".$filtrestatut.")"; + } + + $result = $this->db->query($sql) ; + if ( $result ) + { + $obj=$this->db->fetch_object($result); + $this->stats_expedition['customers']=$obj->nb_customers; + $this->stats_expedition['nb']=$obj->nb; + $this->stats_expedition['rows']=$obj->nb_rows; + $this->stats_expedition['qty']=$obj->qty?$obj->qty:0; + return 1; + } + else + { + $this->error=$this->db->error(); + return -1; + } + } + /** * \brief Charge tableau des stats contrat pour le produit/service * \param socid Id societe @@ -1810,29 +1854,55 @@ class Product extends CommonObject $db->commit(); return 1; } + /** - * \brief fonction r�cursive uniquement utilis�e par get_arbo_each_prod, recompose l'arborescence des sousproduits + * \brief fonction recursive uniquement utilisee par get_arbo_each_prod, recompose l'arborescence des sousproduits * \return void */ - function fetch_prod_arbo($prod,$compl_path="") + function fetch_prod_arbo($prod,$compl_path="",$multiply="") { + global $langs; + $this->res; $this->pere_encours; foreach($prod as $nom_pere => $desc_pere) { - // on est dans une sous-cat�gorie + // on est dans une sous-categorie if(is_array($desc_pere)) - $this->res[]= array($compl_path.stripslashes($nom_pere)." (".$desc_pere[1].")",$desc_pere[0]); - else if($nom_pere != "0" && $nom_pere != "1") - $this->res[]= array($compl_path.stripslashes($nom_pere),$desc_pere); - if(sizeof($desc_pere) >1) - { - $this ->fetch_prod_arbo($desc_pere,stripslashes($nom_pere)." -> "); - } + { + if($multiply) + { + $img=""; + $trueValue=$desc_pere[1]*$multiply; + $product = new Product($this->db); + $this->fetch($desc_pere[0]); + $this->load_stock(); + if ($this->stock_entrepot[1] < $this->seuil_stock_alerte) + { + $img=img_warning($langs->trans("StockTooLow")); + } + $this->res[]= array(" + ", + $desc_pere[0]); + } + else + { + $this->res[]= array($compl_path.$nom_pere." (".$desc_pere[1].")",$desc_pere[0]); + } + } + else if($nom_pere != "0" && $nom_pere != "1") + $this->res[]= array($compl_path.$nom_pere,$desc_pere); + if(sizeof($desc_pere) >1) + { + $this ->fetch_prod_arbo($desc_pere,$nom_pere." -> "); + } } } + /** - * \brief fonction r�cursive uniquement utilis�e par get_each_prod, ajoute chaque sousproduits dans le tableau res + * \brief fonction recursive uniquement utilisee par get_each_prod, ajoute chaque sousproduits dans le tableau res * \return void */ function fetch_prods($prod) @@ -1840,34 +1910,35 @@ class Product extends CommonObject $this->res; foreach($prod as $nom_pere => $desc_pere) { - // on est dans une sous-cat�gorie + // on est dans une sous-categorie if(is_array($desc_pere)) - $this->res[]= array($desc_pere[1],$desc_pere[0]); - if(sizeof($desc_pere) >1) - { - $this ->fetch_prods($desc_pere); - } + $this->res[]= array($desc_pere[1],$desc_pere[0]); + if(sizeof($desc_pere) >1) + { + $this ->fetch_prods($desc_pere); + } } } + /** - * \brief reconstruit l'arborescence des cat�gorie sous la forme d'un tableau + * \brief reconstruit l'arborescence des categorie sous la forme d'un tableau * \return array $this->res */ - function get_arbo_each_prod() + function get_arbo_each_prod($multiply="") { $this->res = array(); if(is_array($this -> sousprods)) { foreach($this -> sousprods as $nom_pere => $desc_pere) - { - if(sizeof($desc_pere) >1) - $this ->fetch_prod_arbo($desc_pere); - - } - sort($this->res); + { + if(sizeof($desc_pere) >1) + $this ->fetch_prod_arbo($desc_pere,"",$multiply); + } + sort($this->res); } return $this->res; } + /** * \brief renvoie tous les sousproduits dans le tableau res, chaque ligne de res contient : id -> qty * \return array $this->res @@ -1878,12 +1949,12 @@ class Product extends CommonObject if(is_array($this -> sousprods)) { foreach($this -> sousprods as $nom_pere => $desc_pere) - { - if(sizeof($desc_pere) >1) - $this ->fetch_prods($desc_pere); + { + if(sizeof($desc_pere) >1) + $this ->fetch_prods($desc_pere); - } - sort($this->res); + } + sort($this->res); } return $this->res; } diff --git a/htdocs/product/sousproduits/fiche.php b/htdocs/product/sousproduits/fiche.php index f211a5c77d6..d7b447966db 100644 --- a/htdocs/product/sousproduits/fiche.php +++ b/htdocs/product/sousproduits/fiche.php @@ -31,7 +31,7 @@ require("./pre.inc.php"); require_once(DOL_DOCUMENT_ROOT."/lib/product.lib.php"); require_once(DOL_DOCUMENT_ROOT."/product.class.php"); require_once(DOL_DOCUMENT_ROOT."/categories/categorie.class.php"); - + $langs->load("bills"); $langs->load("products"); @@ -44,55 +44,55 @@ $action=isset($_GET["action"])?$_GET["action"]:$_POST["action"]; $cancel=isset($_GET["cancel"])?$_GET["cancel"]:$_POST["cancel"]; if ($action <> 're-edit') - { - $product = new Product($db); - if ($id) $result = $product->fetch($id); - if ($ref) $result = $product->fetch($ref); - if ($_GET["ref"]) $result = $product->fetch('',$_GET["ref"]); - if ($_GET["id"]) $result = $product->fetch($_GET["id"]); - } +{ + $product = new Product($db); + if ($id) $result = $product->fetch($id); + if ($ref) $result = $product->fetch($ref); + if ($_GET["ref"]) $result = $product->fetch('',$_GET["ref"]); + if ($_GET["id"]) $result = $product->fetch($_GET["id"]); +} + - if (!$user->rights->produit->lire) accessforbidden(); $html = new Form($db); // Action association d'un sousproduit -if ($action == 'add_prod' && - $cancel <> $langs->trans("Cancel") && - $user->rights->produit->creer) +if ($action == 'add_prod' && +$cancel <> $langs->trans("Cancel") && +$user->rights->produit->creer) { - - for($i=0;$i<$_POST["max_prod"];$i++) + + for($i=0;$i<$_POST["max_prod"];$i++) + { + // print "
: ".$_POST["prod_id_chk".$i]; + if($_POST["prod_id_chk".$i] != "") { - // print "
: ".$_POST["prod_id_chk".$i]; - if($_POST["prod_id_chk".$i] != "") - { - if($product->add_sousproduit($id, $_POST["prod_id_".$i],$_POST["prod_qty_".$i]) > 0) - { - $action = 'edit'; - } - else - { - $action = 're-edit'; - if($product->error == "isFatherOfThis") - $mesg = $langs->trans("ErrorAssociationIsFatherOfThis"); - } - } - else - { - if($product->del_sousproduit($id, $_POST["prod_id_".$i])) - { - $action = 'edit'; - } - else - { - $action = 're-edit'; - } - - - } - } + if($product->add_sousproduit($id, $_POST["prod_id_".$i],$_POST["prod_qty_".$i]) > 0) + { + $action = 'edit'; + } + else + { + $action = 're-edit'; + if($product->error == "isFatherOfThis") + $mesg = $langs->trans("ErrorAssociationIsFatherOfThis"); + } + } + else + { + if($product->del_sousproduit($id, $_POST["prod_id_".$i])) + { + $action = 'edit'; + } + else + { + $action = 're-edit'; + } + + + } + } } // action recherche des produits par mot-cle et/ou par categorie if($action == 'search' ) @@ -100,16 +100,16 @@ if($action == 'search' ) #$sql = 'SELECT p.rowid, p.ref, p.label, p.price, p.fk_product_type'; $sql = 'SELECT p.rowid, p.ref, p.label, p.price'; $sql.= ' FROM '.MAIN_DB_PREFIX.'product as p'; - $sql.= ' left join '.MAIN_DB_PREFIX.'categorie_product as cp on p.rowid=cp.fk_product'; + $sql.= ' left join '.MAIN_DB_PREFIX.'categorie_product as cp on p.rowid=cp.fk_product'; $sql.= " WHERE 1=1"; if($key != "") { $sql .= " AND (p.ref like '%".$key."%'"; $sql .= " OR p.label like '%".$key."%')"; } - if ($conf->categorie->enabled && $catMere != -1 and $catMere) + if ($conf->categorie->enabled && $catMere != -1 and $catMere) { - $sql .= "AND cp.fk_categorie ='".$catMere."'"; + $sql .= "AND cp.fk_categorie ='".$catMere."'"; } $sql .= " ORDER BY p.ref ASC "; // $sql .= $db->plimit($limit + 1 ,$offset); @@ -118,9 +118,9 @@ if($action == 'search' ) if ($cancel == $langs->trans("Cancel")) { - $action = ''; - Header("Location: fiche.php?id=".$_POST["id"]); - exit; + $action = ''; + Header("Location: fiche.php?id=".$_POST["id"]); + exit; } @@ -131,6 +131,12 @@ if ($cancel == $langs->trans("Cancel")) llxHeader("","",$langs->trans("CardProduct".$product->type)); $html = new Form($db); +$productstatic = new Product($db); + +if ($mesg) { + print '
'.$mesg.'

'; +} + $head=product_prepare_head($product, $user); $titre=$langs->trans("CardProduct".$product->type); dolibarr_fiche_head($head, 'subproduct', $titre); @@ -141,217 +147,209 @@ dolibarr_fiche_head($head, 'subproduct', $titre); if ($id || $ref) { - if ( $result ) - { - - if ($action <> 'edit' &&$action <> 'search' && $action <> 're-edit') + + if ( $result ) { - /* - * En mode visu - */ - - print($mesg); - - print '
'; @@ -336,11 +336,12 @@ if ($_GET["id"] > 0) */ print ''; - $sql = "SELECT cd.rowid, cd.fk_product, cd.description, cd.price, cd.qty, cd.tva_tx, cd.subprice"; + $sql = "SELECT cd.fk_product, cd.description, cd.price, sum(cd.qty) as qty, cd.rowid, cd.tva_tx, cd.subprice"; $sql.= " FROM ".MAIN_DB_PREFIX."commandedet as cd"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid"; $sql.= " WHERE cd.fk_commande = ".$commande->id; // $sql.= " AND p.fk_product_type <> 1"; Why this line ? + $sql.= " group by (cd.fk_product)"; $sql.= " ORDER BY cd.rowid"; dolibarr_syslog("commande.php sql=".$sql, LOG_DEBUG); @@ -370,7 +371,7 @@ if ($_GET["id"] > 0) while ($i < $num) { $objp = $db->fetch_object($resql); - + $var=!$var; print ""; if ($objp->fk_product > 0) @@ -390,6 +391,7 @@ if ($_GET["id"] > 0) print ''; + $qtyProdCom=$objp->qty; print '"; + // associations sous produits + $product->get_sousproduits_arbo (); + $prods_arbo = $product->get_arbo_each_prod($qtyProdCom); + if(sizeof($prods_arbo) > 0) + { + foreach($prods_arbo as $key => $value) + { + print $value[0]; + } + } + $i++; $var=!$var; } @@ -445,7 +458,7 @@ if ($_GET["id"] > 0) if ($user->societe_id == 0) { print '
'; - + // Bouton expedier sans gestion des stocks if (! $conf->stock->enabled && $reste_a_livrer_total > 0 && ! $commande->brouillon && $user->rights->expedition->creer) { @@ -472,11 +485,11 @@ if ($_GET["id"] > 0) $entrepot = new Entrepot($db); $langs->load("stocks"); - + print '
'; print ''; print '
'.$objp->qty.''; // Nb of sending products for this line of order $quantite_livree = $commande->expeditions[$objp->rowid]; @@ -418,6 +420,17 @@ if ($_GET["id"] > 0) } print "
'.$langs->trans("Warehouse").''; - + if (sizeof($user->entrepots) === 1) { $uentrepot = array(); @@ -506,7 +519,7 @@ if ($_GET["id"] > 0) print "
"; print "\n"; - + $somethingshown=1; } diff --git a/htdocs/expedition/fiche.php b/htdocs/expedition/fiche.php index 4577c3a5e8d..434499f590c 100644 --- a/htdocs/expedition/fiche.php +++ b/htdocs/expedition/fiche.php @@ -354,6 +354,7 @@ if ($_GET["action"] == 'create') } print '
'.$ligne->qty.''; $quantityDelivered = $object->expeditions[$ligne->id]; @@ -423,6 +424,7 @@ if ($_GET["action"] == 'create') $html->select_array('entl'.$i,$array,'',1,0,0); print '
      + ".$compl_path.stripslashes($nom_pere)." + ".$trueValue."  ".$this->stock_entrepot[1]." ".$img."
'; - - print ""; - - $nblignes=6; - if ($product->isproduct() && $conf->stock->enabled) $nblignes++; - if ($product->isservice()) $nblignes++; - - // Reference - print ''; - - // Libelle - print ''; - print ''; - - $product->get_sousproduits_arbo (); - print ''; - - // associations sousproduits - $prods_arbo = $product->get_arbo_each_prod(); - if(sizeof($prods_arbo) > 0) - { - print ''; - } - - print "
'.$langs->trans("Ref").''; - print $html->showrefnav($product,'ref','',1,'ref'); - print '
'.$langs->trans("Label").''.$product->libelle.'
'.$langs->trans("AssociatedProductsNumber").''.sizeof($product->get_arbo_each_prod()).'
'; - print ''.$langs->trans("ProductAssociationList").'
'; - foreach($prods_arbo as $key => $value) + + if ($action <> 'edit' &&$action <> 'search' && $action <> 're-edit') { - print '- '.$value[0].'
'; - } - - - print '
\n"; - - print "\n"; - } - } - - /* - * Fiche en mode edition - */ - if (($action == 'edit' || $action == 'search' || $action == 're-edit') && $user->rights->produit->creer) - { + /* + * En mode visu + */ - if ($product->isservice()) { - print_fiche_titre($langs->trans('EditAssociate').' '.$langs->trans('Service').' : '.$product->ref, ""); - } else { - print_fiche_titre($langs->trans('EditAssociate').' '.$langs->trans('Product').' : '.$product->ref, ""); - } + print ''; - if ($mesg) { - print '
'.$mesg.'

'; - } + print ""; - print '
'; + $nblignes=6; + if ($product->isproduct() && $conf->stock->enabled) $nblignes++; + if ($product->isservice()) $nblignes++; - print ""; + // Reference + print ''; - $nblignes=6; - if ($product->isproduct() && $conf->stock->enabled) $nblignes++; - if ($product->isservice()) $nblignes++; + // Libelle + print ''; + print ''; - // Reference - print ''; - - if ($product->is_photo_available($conf->produit->dir_output)) - { - // Photo - print ''; - } - - print ''; - - // Libelle - print ''; - print ''; - // Nombre de sousproduits associ�s $product->get_sousproduits_arbo (); - print ''; - print ''; - print ''; print ''; - - // Calculating a theorical value of stock if stock increment is done on order - if ($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) + // Calculating a theorical value of stock if stock increment is done on real sending + if ($conf->global->STOCK_CALCULATE_ON_SHIPMENT) { $stock_commande_client=$stock_commande_fournisseur=0; if ($conf->commande->enabled) { - $result=$product->load_stats_commande(0,'2'); + $result=$product->load_stats_commande(0,'1,2'); if ($result < 0) dolibarr_print_error($db,$product->error); $stock_commande_client=$product->stats_commande['qty']; } @@ -166,7 +165,7 @@ if ($_GET["id"] || $_GET["ref"]) $stock_commande_fournisseur=$product->stats_commande_fournisseur['qty']; } - $product->stock_theorique=$product->stock_reel-$stock_commande_client+$stock_commande_fournisseur; + $product->stock_theorique=$product->stock_reel-($stock_commande_client+$stock_sending_client)+$stock_commande_fournisseur; // Stock theorique print ''; @@ -190,10 +189,12 @@ if ($_GET["id"] || $_GET["ref"]) if ($conf->commande->enabled) { if ($found) print '
'; else $found=1; - print $langs->trans("CustomersOrdersRunning").': '.$stock_commande_client; - $result=$product->load_stats_commande(0,'0,1'); + print $langs->trans("CustomersOrdersRunning").': '.($stock_commande_client+$stock_sending_client); + $result=$product->load_stats_commande(0,'0'); if ($result < 0) dolibarr_print_error($db,$product->error); - print ' ('.$langs->trans("DraftOrWaitingShipped").': '.$product->stats_commande['qty'].')'; + print ' ('.$langs->trans("Draft").': '.$product->stats_commande['qty'].')'; + //print '
'; + //print $langs->trans("CustomersSendingRunning").': '.$stock_sending_client; } // Nbre de commande fournisseurs en cours
'.$langs->trans("Ref").''; + print $html->showrefnav($product,'ref','',1,'ref'); + print '
'.$langs->trans("Label").''.$product->libelle.'
'.$langs->trans("Ref").''; - print ''.$product->ref.''; - print ''; - $nbphoto=$product->show_photos($conf->produit->dir_output,1,1,0); - print '
'.$langs->trans("Label").''.$product->libelle.'
'.$langs->trans("AssociatedProductsNumber").''.sizeof($product->get_arbo_each_prod()).'
'.$langs->trans("ProductToAddSearch").''; - print ''; - print ''; - - if($conf->categorie->enabled) + print ''; + + // associations sousproduits + $prods_arbo = $product->get_arbo_each_prod(); + if(sizeof($prods_arbo) > 0) { - print ''; - } - - print ''; - print ''; - print ''; + print ''; + print '
'; - print $langs->trans("KeywordFilter"); - print '
'; - print ''; - print ''; - print '
'.$langs->trans("AssociatedProductsNumber").''.sizeof($product->get_arbo_each_prod()).'
'.$langs->trans("CategoryFilter"); - print ''.$html->select_all_categories(0,$catMere).'

'; - - if($action == 'search') - { - print ''; - print ''; - print ''; - print ''; - print ''; - while ($i < $num) + $productstatic->id=$value[1]; + $productstatic->type=0; + $productstatic->ref=$value[0]; + print $productstatic->getNomUrl(1).'
'; + } + + + print ''; + } + + print "
'.$langs->trans("Ref").''.$langs->trans("Label").''.$langs->trans("AddDel").''.$langs->trans("Quantity").'
'; + print ''.$langs->trans("ProductAssociationList").'
'; + foreach($prods_arbo as $key => $value) { - $num = $db->num_rows($resql); - $i=0; - if($num == 0) - print '
'.$langs->trans("NoMatchFound").'
\n"; + + print "\n"; + } + } + + /* + * Fiche en mode edition + */ + if (($action == 'edit' || $action == 'search' || $action == 're-edit') && $user->rights->produit->creer) + { + print ''; + + print ""; + + $nblignes=6; + if ($product->isproduct() && $conf->stock->enabled) $nblignes++; + if ($product->isservice()) $nblignes++; + + // Reference + print ''; + + if ($product->is_photo_available($conf->produit->dir_output)) + { + // Photo + print ''; + } + + print ''; + + // Libelle + print ''; + print ''; + // Nombre de sousproduits associes + $product->get_sousproduits_arbo (); + print ''; + print ''; + print ''; - print ''; - print '
'.$langs->trans("Ref").''; + print $html->showrefnav($product,'ref','',1,'ref'); + print '
'; + $nbphoto=$product->show_photos($conf->produit->dir_output,1,1,0); + print '
'.$langs->trans("Label").''.$product->libelle.'
'.$langs->trans("AssociatedProductsNumber").''.sizeof($product->get_arbo_each_prod()).'
'.$langs->trans("ProductToAddSearch").''; + print ''; + print ''; + + if($conf->categorie->enabled) + { + print ''; + } + + print ''; + print ''; + print ''; + print '
'; + print $langs->trans("KeywordFilter"); + print ''; + print ''; + print ''; + print '
'.$langs->trans("CategoryFilter"); + print ''.$html->select_all_categories(0,$catMere).'

'; + + if($action == 'search') + { + print ''; + print ''; + print ''; + print ''; + print 'num_rows($resql); + $i=0; + if($num == 0) + print ''; + while ($i < $num) + { + $objp = $db->fetch_object($resql); + if($objp->rowid != $id) { - $objp = $db->fetch_object($resql); - if($objp->rowid != $id) + // check if a product is not already a parent product of this one + $prod_arbo=new Product($db,$objp->rowid); + if ($prod_arbo->type==2 || $prod_arbo->type==3) { - // check if a product is not already a parent product of this one - $prod_arbo=new Product($db,$objp->rowid); - if ($prod_arbo->type==2 || $prod_arbo->type==3) { - $is_pere=0; - $prod_arbo->get_sousproduits_arbo (); - // associations sousproduits - $prods_arbo = $prod_arbo->get_arbo_each_prod(); - if(sizeof($prods_arbo) > 0) { - foreach($prods_arbo as $key => $value) { - if ($value[1]==$id) { - $is_pere=1; - } - } - } - if ($is_pere==1) { - $i++; - continue; - } - } - print "\n"; - print ''; - print ''; - if($product->is_sousproduit($id, $objp->rowid)) - { - $addchecked = ' checked="true"'; - $qty=$product->is_sousproduit_qty; + $is_pere=0; + $prod_arbo->get_sousproduits_arbo (); + // associations sousproduits + $prods_arbo = $prod_arbo->get_arbo_each_prod(); + if(sizeof($prods_arbo) > 0) { + foreach($prods_arbo as $key => $value) { + if ($value[1]==$id) { + $is_pere=1; + } + } } - else - { - $addchecked = ''; - $qty="1"; + if ($is_pere==1) { + $i++; + continue; } - print ''; - print ''; - print ''; - print ''; } - $i++; - } + print "\n"; + print ''; + print ''; + if($product->is_sousproduit($id, $objp->rowid)) + { + $addchecked = ' checked="true"'; + $qty=$product->is_sousproduit_qty; + } + else + { + $addchecked = ''; + $qty="1"; + } + print ''; + print ''; + print ''; + print ''; + } + $i++; + } - } - else - { - dolibarr_print_error($db); - } - print ''; - if($num > 0) - print ''; - print '
'.$langs->trans("Ref").''.$langs->trans("Label").''.$langs->trans("AddDel").''.$langs->trans("Quantity").'
'.$langs->trans("NoMatchFound").'
'.$objp->ref.''.$objp->label.''; - print '
'.$objp->ref.''.$objp->label.''; + print '
'; } + else + { + dolibarr_print_error($db); + } + print ''; + if($num > 0) + print '
'; + } - print '
'; - } + print '
'; + } } /* ************************************************************************** */ -/* */ -/* Barre d'action */ -/* */ +/* */ +/* Barre d'action */ +/* */ /* ************************************************************************** */ print "\n
\n"; if ($action == '') { - - if ( $user->rights->produit->creer) - { - print ''.$langs->trans("Modify").''; - } + if ( $user->rights->produit->creer) + { + print ''.$langs->trans("EditAssociate").''; + + } } diff --git a/htdocs/product/stock/mouvementstock.class.php b/htdocs/product/stock/mouvementstock.class.php index 119734a659b..aa01a1dd7bc 100644 --- a/htdocs/product/stock/mouvementstock.class.php +++ b/htdocs/product/stock/mouvementstock.class.php @@ -21,390 +21,422 @@ */ /** - \file htdocs/product/stock/mouvementstock.class.php - \ingroup stock - \brief Fichier de la classe de gestion des mouvements de stocks - \version $Revision$ -*/ + \file htdocs/product/stock/mouvementstock.class.php + \ingroup stock + \brief Fichier de la classe de gestion des mouvements de stocks + \version $Revision$ + */ /** - \class MouvementStock - \brief Classe permettant la gestion des mouvements de stocks -*/ + \class MouvementStock + \brief Classe permettant la gestion des mouvements de stocks + */ class MouvementStock { - function MouvementStock($DB) - { - $this->db = $DB; - } - - /** - * \brief Crée un mouvement en base - * \return int <0 si ko, >0 si ok - */ - function _create($user, $fk_product, $entrepot_id, $qty, $type, $price=0) - { - $error = 0; - dolibarr_syslog("MouvementStock::_Create $user->id, $fk_product, $entrepot_id, $qty, $type, $price"); - - $this->db->begin(); - - $sql = "INSERT INTO ".MAIN_DB_PREFIX."stock_mouvement"; - $sql.= " (datem, fk_product, fk_entrepot, value, type_mouvement, fk_user_author, price)"; - $sql.= " VALUES (".$this->db->idate(mktime()).", ".$fk_product.", ".$entrepot_id.", ".$qty.", ".$type.", ".$user->id; - $sql.= ",'".price2num($price)."')"; - - if ($resql = $this->db->query($sql)) - { - $mvid = $this->db->last_insert_id($resql); - } - else - { - dolibarr_syslog("MouvementStock::_Create echec insert ".$this->error); - $error = -1; - } - - $num = 0; - - if ($error === 0) - { - $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."product_stock"; - $sql.= " WHERE fk_entrepot = ".$entrepot_id." AND fk_product = ".$fk_product; - - if ($this->db->query($sql)) - { - $num = $this->db->num_rows($resql); - $this->db->free($resql); - } - else - { - dolibarr_syslog("MouvementStock::_Create echec update ".$this->error); - $error = -2; - } - } - - if ($error === 0) - { - if ($num > 0) - { - $sql = "UPDATE ".MAIN_DB_PREFIX."product_stock SET reel = reel + ".$qty; - $sql.= " WHERE fk_entrepot = ".$entrepot_id." AND fk_product = ".$fk_product; - } - else - { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_stock"; - $sql.= " (reel, fk_entrepot, fk_product) VALUES "; - $sql.= " (".$qty.",".$entrepot_id.",".$fk_product.")"; - } - - if ($this->db->query($sql)) - { - - } - else - { - dolibarr_syslog("MouvementStock::_Create echec update ".$this->error); - $error = -3; - } - } - - if ($error === 0) - { - $valo_mouvement = 0; - $error = $this->CalculateValoPmp($mvid, $fk_product, $qty, $price, $valo_mouvement); - } - - if ($error === 0) - { - $error = $this->CalculateEntrepotValoPmp($user, $entrepot_id, $valo_mouvement); - } - - if ($error === 0) - { - $error = $this->_createSubProduct($user, $fk_product, $entrepot_id, $qty, $type, $price=0); - } - - if ($error === 0) - { - $this->db->commit(); - return 1; - } - else - { - $this->db->rollback(); - $this->error=$this->db->error() . " - $sql"; - dolibarr_syslog("MouvementStock::_Create ERROR : ".$this->error); - return -2; - } - } - - - /** - * \brief Crée un mouvement en base pour tous les sous-produits - * \return int <0 si ko, 0 si ok - */ - function _createSubProduct($user, $fk_product, $entrepot_id, $qty, $type, $price=0) - { - $error = 0; - dolibarr_syslog("MouvementStock::_CreateSubProduct $user->id, $fk_product, $entrepot_id, $qty, $type, $price"); - $pids = array(); - - $sql = "SELECT fk_product_subproduct FROM ".MAIN_DB_PREFIX."product_subproduct"; - $sql.= " WHERE fk_product = $fk_product;"; - - if ($this->db->query($sql)) - { - while ($row = $this->db->fetch_row($resql) ) - { - array_push($row[0]); - } - $this->db->free($resql); - } - else - { - dolibarr_syslog("MouvementStock::_Create echec update ".$this->error); - $error = -2; - } - - foreach($pids as $pid) - { - $this->_create($user, $pid, $entrepot_id, $qty, $type, $price=0); - } - - return $error; - } - - - - /** - * \brief Calcul ??? - * \return int <0 si ko, >0 si ok - */ - function CalculateEntrepotValoPmp($user, $entrepot_id, $valo_mouvement) - { - $error = 0; - dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp $user->id, $entrepot_id, $valo_mouvement"); - - if ( $valo_mouvement <> 0 ) + function MouvementStock($DB) { + $this->db = $DB; + } + + /** + * \brief Add a mouvement in stock (in one direction only) + * \param type Direction of movement: 2=output (stock decrease), 3=input (stock increase) + * \return int <0 if KO, >0 if OK + */ + function _create($user, $fk_product, $entrepot_id, $qty, $type, $price=0) + { + $error = 0; + dolibarr_syslog("MouvementStock::_Create $user->id, $fk_product, $entrepot_id, $qty, $type, $price"); + + $this->db->begin(); + + // $nbOfSubproduct=$this->nbOfSubProdcuts(); + + if (1 == 1) // Always change stock for current product + { + $sql = "INSERT INTO ".MAIN_DB_PREFIX."stock_mouvement"; + $sql.= " (datem, fk_product, fk_entrepot, value, type_mouvement, fk_user_author, price)"; + $sql.= " VALUES (".$this->db->idate(mktime()).", ".$fk_product.", ".$entrepot_id.", ".$qty.", ".$type.", ".$user->id; + $sql.= ",'".price2num($price)."')"; + + dolibarr_syslog("MouvementStock::_create sql=".$sql, LOG_DEBUG); + if ($resql = $this->db->query($sql)) + { + $mvid = $this->db->last_insert_id($resql); + } + else + { + dolibarr_syslog("MouvementStock::_Create echec insert ".$this->error); + $error = -1; + } + + // Get current value of stock + $num = 0; + if ($error == 0) + { + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."product_stock"; + $sql.= " WHERE fk_entrepot = ".$entrepot_id." AND fk_product = ".$fk_product; + + if ($this->db->query($sql)) + { + $num = $this->db->num_rows($resql); + $this->db->free($resql); + } + else + { + dolibarr_syslog("MouvementStock::_Create echec update ".$this->error); + $error = -2; + } + } + + // Update value + if ($error == 0) + { + if ($num > 0) + { + $sql = "UPDATE ".MAIN_DB_PREFIX."product_stock SET reel = reel + ".$qty; + $sql.= " WHERE fk_entrepot = ".$entrepot_id." AND fk_product = ".$fk_product; + } + else + { + $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_stock"; + $sql.= " (reel, fk_entrepot, fk_product) VALUES "; + $sql.= " (".$qty.",".$entrepot_id.",".$fk_product.")"; + } + + dolibarr_syslog("MouvementStock::_create sql=".$sql, LOG_DEBUG); + if ($this->db->query($sql)) + { + + } + else + { + dolibarr_syslog("MouvementStock::_Create echec update ".$this->error); + $error = -3; + } + } + + if ($error == 0) + { + $valo_mouvement = 0; + $error = $this->CalculateValoPmp($mvid, $fk_product, $qty, $price, $valo_mouvement); + } + + if ($error == 0) + { + $error = $this->CalculateEntrepotValoPmp($user, $entrepot_id, $valo_mouvement); + } + } + + // Add movement for sub products + $error = $this->_createSubProduct($user, $fk_product, $entrepot_id, $qty, $type, $price=0); + + if ($error == 0) + { + $this->db->commit(); + return 1; + } + else + { + $this->db->rollback(); + $this->error=$this->db->error() . " - $sql"; + dolibarr_syslog("MouvementStock::_Create ERROR : ".$this->error); + return -2; + } + } + + + /** + * \brief Crée un mouvement en base pour tous les sous-produits + * \return int <0 si ko, 0 si ok + */ + function _createSubProduct($user, $idProduct, $entrepot_id, $qty, $type, $price=0) + { + $error = 0; + $pids = array(); + + $sql = "SELECT fk_product_pere, fk_product_fils, qty"; + $sql.= " FROM ".MAIN_DB_PREFIX."product_association"; + $sql.= " WHERE fk_product_pere = ".$idProduct; + + dolibarr_syslog("MouvementStock::_createSubProduct sql=".$sql, LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + while ($obj=$this->db->fetch_object($resql)) + { + $pids[]=$obj->fk_product_fils; + } + $this->db->free($resql); + } + else + { + dolibarr_syslog("MouvementStock::_createSubProduct echec update ".$this->error, LOG_ERROR); + $error = -2; + } + + // Create movement for each subproduct + foreach($pids as $pid) + { + $this->_create($user, $pid, $entrepot_id, $qty, $type, $price); + } + + return $error; + } + + + + /** + * \brief Calcul ??? + * \return int <0 si ko, >0 si ok + */ + function CalculateEntrepotValoPmp($user, $entrepot_id, $valo_mouvement) + { + $error = 0; + dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp $user->id, $entrepot_id, $valo_mouvement"); + + if ( $valo_mouvement <> 0 ) + { $entrepot_value_pmp = 0; - + if ($error === 0) - { - $sql = "SELECT valo_pmp,".$this->db->pdate("date_calcul")." FROM ".MAIN_DB_PREFIX."entrepot_valorisation"; - $sql.= " WHERE fk_entrepot = $entrepot_id ORDER BY date_calcul DESC LIMIT 1;"; - - if ($this->db->query($sql)) - { - while ($row = $this->db->fetch_row($resql) ) - { - $entrepot_value_pmp = $row[0]; - $entrepot_value_date = $row[1]; - } - $this->db->free($resql); - } - else - { - $error = -26; - dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]"); - } - } + { + $sql = "SELECT valo_pmp,".$this->db->pdate("date_calcul")." FROM ".MAIN_DB_PREFIX."entrepot_valorisation"; + $sql.= " WHERE fk_entrepot = $entrepot_id ORDER BY date_calcul DESC LIMIT 1;"; + + if ($this->db->query($sql)) + { + while ($row = $this->db->fetch_row($resql) ) + { + $entrepot_value_pmp = $row[0]; + $entrepot_value_date = $row[1]; + } + $this->db->free($resql); + } + else + { + $error = -26; + dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]"); + } + } $new_value = $entrepot_value_pmp + $valo_mouvement; $now = time(); if ($error === 0) - { - if ( strftime('%Y%m%d',$entrepot_value_date) == strftime('%Y%m%d',$now) ) - { - $sql = "UPDATE ".MAIN_DB_PREFIX."entrepot_valorisation"; - $sql.= " SET valo_pmp='".ereg_replace(",",".",$new_value)."'"; - $sql.= " WHERE fk_entrepot = $entrepot_id "; - $sql.= " AND ".$this->db->pdate("date_calcul")."='".$entrepot_value_date."';"; - } - else - { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."entrepot_valorisation"; - $sql.= " (date_calcul, fk_entrepot, valo_pmp)"; - $sql.= " VALUES (".$this->db->idate(mktime()).", ".$entrepot_id; - $sql.= ",'".ereg_replace(",",".",$new_value)."');"; - } - - if ($this->db->query($sql)) - { - - } - else - { - $error = -27; - dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]"); - } - } + { + if ( strftime('%Y%m%d',$entrepot_value_date) == strftime('%Y%m%d',$now) ) + { + $sql = "UPDATE ".MAIN_DB_PREFIX."entrepot_valorisation"; + $sql.= " SET valo_pmp='".ereg_replace(",",".",$new_value)."'"; + $sql.= " WHERE fk_entrepot = $entrepot_id "; + $sql.= " AND ".$this->db->pdate("date_calcul")."='".$entrepot_value_date."';"; + } + else + { + $sql = "INSERT INTO ".MAIN_DB_PREFIX."entrepot_valorisation"; + $sql.= " (date_calcul, fk_entrepot, valo_pmp)"; + $sql.= " VALUES (".$this->db->idate(mktime()).", ".$entrepot_id; + $sql.= ",'".ereg_replace(",",".",$new_value)."');"; + } + + if ($this->db->query($sql)) + { + + } + else + { + $error = -27; + dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]"); + } + } if ($error === 0) - { - $sql = "UPDATE ".MAIN_DB_PREFIX."entrepot"; - $sql.= " SET valo_pmp='".ereg_replace(",",".",$new_value)."'"; - $sql.= " WHERE rowid = $entrepot_id "; - - if ($this->db->query($sql)) - { - - } - else - { - $error = -28; - dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]"); - } - } - + { + $sql = "UPDATE ".MAIN_DB_PREFIX."entrepot"; + $sql.= " SET valo_pmp='".ereg_replace(",",".",$new_value)."'"; + $sql.= " WHERE rowid = $entrepot_id "; + + if ($this->db->query($sql)) + { + + } + else + { + $error = -28; + dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]"); + } + } + if ($error === 0) - { - return 0; - } + { + return 0; + } else - { - dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp RETURN IN ERROR[$error]"); - return $error; - } - } - else - { + { + dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp RETURN IN ERROR[$error]"); + return $error; + } + } + else + { return 0; + } } - } - - - /** - * \brief ??? - * \param mvid int Id du mouvement - * \param fk_product int Id produit - * \param qty float Quantité - * \param price float Prix unitaire du produit - * \param value_ope float Valeur du mouvement en retour - * \return int <0 si ko, 0 si ok - */ - function CalculateValoPmp($mvid, $fk_product, $qty, $price=0, &$value_ope) - { - $error = 0; - dolibarr_syslog("MouvementStock::CalculateValoPmp $mvid, $fk_product, $qty, $price"); - if ( $qty <> 0 ) + + /** + * \brief ??? + * \param mvid int Id du mouvement + * \param fk_product int Id produit + * \param qty float Quantité + * \param price float Prix unitaire du produit + * \param value_ope float Valeur du mouvement en retour + * \return int <0 si ko, 0 si ok + */ + function CalculateValoPmp($mvid, $fk_product, $qty, $price=0, &$value_ope) { - $price_pmp = 0; - $qty_stock = 0; - $stock_value_pmp = 0; - - if ($error === 0) - { - $sql = "SELECT price_pmp, qty_stock, valo_pmp FROM ".MAIN_DB_PREFIX."stock_valorisation"; - $sql.= " WHERE fk_product = $fk_product ORDER BY date_valo DESC LIMIT 1;"; - - if ($this->db->query($sql)) - { - while ($row = $this->db->fetch_row($resql) ) - { - $price_pmp = $row[0]; - $qty_stock = $row[1]; - $stock_value_pmp = $row[2]; - } - $this->db->free($resql); - } - else - { - dolibarr_syslog("MouvementStock::CalculateValoPmp ERRORSQL[1] ".$this->error); - $error = -16; - } - } + $error = 0; + dolibarr_syslog("MouvementStock::CalculateValoPmp $mvid, $fk_product, $qty, $price"); - /* - * Calcul - */ - if ($qty > 0) - { - // on stock - if (($qty + $qty_stock) <> 0) - $new_pmp = ( ($qty * $price) + ($qty_stock * $price_pmp ) ) / ($qty + $qty_stock); - - $value_ope = $qty * $price; - $new_stock_qty = $qty_stock + $qty; - $new_stock_value_pmp = $stock_value_pmp + $value_ope; - } - else - { - // on destock - $new_pmp = $price_pmp; - $price = $price_pmp; - $value_ope = $qty * $price_pmp; - } - - $new_stock_qty = $qty_stock + $qty; - $new_stock_value_pmp = $stock_value_pmp + $value_ope; - /* - * Fin calcul - */ - if ($error === 0) - { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."stock_valorisation"; - $sql.= " (date_valo, fk_product, fk_stock_mouvement, qty_ope, price_ope, valo_ope, price_pmp, qty_stock, valo_pmp)"; - $sql.= " VALUES (".$this->db->idate(mktime()).", $fk_product, $mvid"; - $sql.= ",'".price2num($qty)."'"; - $sql.= ",'".price2num($price)."'"; - $sql.= ",'".price2num($value_ope)."'"; - $sql.= ",'".price2num($new_pmp)."'"; - $sql.= ",'".price2num($new_stock_qty)."'"; - $sql.= ",'".price2num($new_stock_value_pmp)."')"; - - if ($this->db->query($sql)) + if ( $qty <> 0 ) { - + $price_pmp = 0; + $qty_stock = 0; + $stock_value_pmp = 0; + + if ($error === 0) + { + $sql = "SELECT price_pmp, qty_stock, valo_pmp FROM ".MAIN_DB_PREFIX."stock_valorisation"; + $sql.= " WHERE fk_product = $fk_product ORDER BY date_valo DESC LIMIT 1;"; + + if ($this->db->query($sql)) + { + while ($row = $this->db->fetch_row($resql) ) + { + $price_pmp = $row[0]; + $qty_stock = $row[1]; + $stock_value_pmp = $row[2]; + } + $this->db->free($resql); + } + else + { + dolibarr_syslog("MouvementStock::CalculateValoPmp ERRORSQL[1] ".$this->error); + $error = -16; + } + } + + /* + * Calcul + */ + if ($qty > 0) + { + // on stock + if (($qty + $qty_stock) <> 0) + $new_pmp = ( ($qty * $price) + ($qty_stock * $price_pmp ) ) / ($qty + $qty_stock); + + $value_ope = $qty * $price; + $new_stock_qty = $qty_stock + $qty; + $new_stock_value_pmp = $stock_value_pmp + $value_ope; + } + else + { + // on destock + $new_pmp = $price_pmp; + $price = $price_pmp; + $value_ope = $qty * $price_pmp; + } + + $new_stock_qty = $qty_stock + $qty; + $new_stock_value_pmp = $stock_value_pmp + $value_ope; + /* + * Fin calcul + */ + if ($error === 0) + { + $sql = "INSERT INTO ".MAIN_DB_PREFIX."stock_valorisation"; + $sql.= " (date_valo, fk_product, fk_stock_mouvement, qty_ope, price_ope, valo_ope, price_pmp, qty_stock, valo_pmp)"; + $sql.= " VALUES (".$this->db->idate(mktime()).", $fk_product, $mvid"; + $sql.= ",'".price2num($qty)."'"; + $sql.= ",'".price2num($price)."'"; + $sql.= ",'".price2num($value_ope)."'"; + $sql.= ",'".price2num($new_pmp)."'"; + $sql.= ",'".price2num($new_stock_qty)."'"; + $sql.= ",'".price2num($new_stock_value_pmp)."')"; + + if ($this->db->query($sql)) + { + + } + else + { + dolibarr_syslog("MouvementStock::CalculateValoPmp ERRORSQL[2] insert ".$this->error); + $error = -17; + } + } + + if ($error === 0) + { + return 0; + } + else + { + dolibarr_syslog("MouvementStock::CalculateValoPmp ERROR : $error"); + return -21; + } } - else - { - dolibarr_syslog("MouvementStock::CalculateValoPmp ERRORSQL[2] insert ".$this->error); - $error = -17; + else + { + return 0; } - } - - if ($error === 0) - { - return 0; - } - else - { - dolibarr_syslog("MouvementStock::CalculateValoPmp ERROR : $error"); - return -21; - } } - else + + + /** + * \brief Decrease stock for product and subproducts + * + */ + function livraison($user, $fk_product, $entrepot_id, $qty) { - return 0; + return $this->_create($user, $fk_product, $entrepot_id, (0 - $qty), 2); + } + + + /** + * \brief Increase stock for product and subproducts + * + */ + function reception($user, $fk_product, $entrepot_id, $qty, $price=0) + { + return $this->_create($user, $fk_product, $entrepot_id, $qty, 3, $price); + } + + + /** + * Return nb of subproducts for a product + * + * @param unknown_type $id + * @return unknown + */ + function nbOfSubProdcuts($id) + { + $nbSP=0; + + $resql = "SELECT count(*) as nb FROM ".MAIN_DB_PREFIX."product_association"; + $resql.= " WHERE fk_product_pere = ".$id; + if ($this->db->query($resql)) + { + $obj=$this->db->fetch_object($resql); + $nbSP=$obj->nb; + } + $this->db->free($resql); + return $nbSP; } - } - - - /* - * - * - */ - function livraison($user, $fk_product, $entrepot_id, $qty) - { - return $this->_create($user, $fk_product, $entrepot_id, (0 - $qty), 2); - } - - - /* - * - * - */ - function reception($user, $fk_product, $entrepot_id, $qty, $price=0) - { - return $this->_create($user, $fk_product, $entrepot_id, $qty, 3, $price); - } } ?> diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index fcfa18ccdfd..43a8ffcbefe 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -147,15 +147,14 @@ if ($_GET["id"] || $_GET["ref"]) print '
'.$product->stock_reel.'
'.$langs->trans("VirtualStock").'