Fix: Maxi debug on stock decrease

This commit is contained in:
Laurent Destailleur 2008-10-23 21:54:30 +00:00
parent 18f10649c2
commit d1a90768cd
19 changed files with 1027 additions and 889 deletions

View File

@ -19,10 +19,10 @@
/** /**
\file htdocs/admin/stock.php \file htdocs/admin/stock.php
\ingroup stock \ingroup stock
\brief Page d'administration/configuration du module gestion de stock \brief Page d'administration/configuration du module gestion de stock
\version $Id$ \version $Id$
*/ */
require("./pre.inc.php"); require("./pre.inc.php");
require_once(DOL_DOCUMENT_ROOT."/lib/admin.lib.php"); require_once(DOL_DOCUMENT_ROOT."/lib/admin.lib.php");
@ -30,32 +30,32 @@ $langs->load("admin");
$langs->load("stocks"); $langs->load("stocks");
if (!$user->admin) if (!$user->admin)
accessforbidden(); accessforbidden();
/* /*
* Actions * Actions
*/ */
if ($_POST["action"] == 'stock_userstock') if ($_POST["action"] == 'stock_userstock')
{ {
dolibarr_set_const($db, "STOCK_USERSTOCK", $_POST["stock_userstock"]); dolibarr_set_const($db, "STOCK_USERSTOCK", $_POST["stock_userstock"]);
//On d<>sactive l'autocr<63>ation si l'option "stock personnel" est d<>sactiv<69>e //On d<>sactive l'autocr<63>ation si l'option "stock personnel" est d<>sactiv<69>e
if ($_POST["stock_userstock"] == 0) if ($_POST["stock_userstock"] == 0)
{ {
dolibarr_set_const($db, "STOCK_USERSTOCK_AUTOCREATE", 0); dolibarr_set_const($db, "STOCK_USERSTOCK_AUTOCREATE", 0);
} }
Header("Location: stock.php"); Header("Location: stock.php");
exit; exit;
} }
elseif ($_POST["action"] == 'stock_userstock_autocreate') elseif ($_POST["action"] == 'stock_userstock_autocreate')
{ {
dolibarr_set_const($db, "STOCK_USERSTOCK_AUTOCREATE", $_POST["stock_userstock_autocreate"]); dolibarr_set_const($db, "STOCK_USERSTOCK_AUTOCREATE", $_POST["stock_userstock_autocreate"]);
Header("Location: stock.php"); Header("Location: stock.php");
exit; exit;
} }
// Mode of stock changement // Mode of stock changement
elseif ( $_POST["action"] == 'stock_bill' elseif ( $_POST["action"] == 'stock_bill'
|| $_POST["action"] == 'stock_validateorder' || $_POST["action"] == 'stock_validateorder'
|| $_POST["action"] == 'stock_shipment') || $_POST["action"] == 'stock_shipment')
{ {
$count=0; $count=0;
$db->begin(); $db->begin();
@ -68,13 +68,13 @@ elseif ( $_POST["action"] == 'stock_bill'
if ($count == 4) if ($count == 4)
{ {
$db->commit(); $db->commit();
Header("Location: stock.php"); Header("Location: stock.php");
exit; exit;
} }
else else
{ {
$db->rollback(); $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 "</form>\n</td>\n</tr>\n";
if ($conf->global->STOCK_USERSTOCK == 1) if ($conf->global->STOCK_USERSTOCK == 1)
{ {
$var=!$var; $var=!$var;
print "<tr ".$bc[$var].">"; print "<tr ".$bc[$var].">";
print '<td width="60%">'.$langs->trans("UserWarehouseAutoCreate").'</td>'; print '<td width="60%">'.$langs->trans("UserWarehouseAutoCreate").'</td>';
print '<td width="160" align="right">'; print '<td width="160" align="right">';
print "<form method=\"post\" action=\"stock.php\">"; print "<form method=\"post\" action=\"stock.php\">";
print "<input type=\"hidden\" name=\"action\" value=\"stock_userstock_autocreate\">"; print "<input type=\"hidden\" name=\"action\" value=\"stock_userstock_autocreate\">";
print $html->selectyesno("stock_userstock_autocreate",$conf->global->STOCK_USERSTOCK_AUTOCREATE,1); print $html->selectyesno("stock_userstock_autocreate",$conf->global->STOCK_USERSTOCK_AUTOCREATE,1);
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">'; print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print '</form>'; print '</form>';
print "</td>\n"; print "</td>\n";
print "</tr>\n"; print "</tr>\n";
} }
// Title rule for stock decrease
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
print " <td>".$langs->trans("RuleForStockManagement")."</td>\n"; print " <td>".$langs->trans("RuleForStockManagementDecrease")."</td>\n";
print " <td align=\"right\" width=\"160\">".$langs->trans("Value")."</td>\n"; print " <td align=\"right\" width=\"160\">".$langs->trans("Value")."</td>\n";
print '</tr>'."\n"; print '</tr>'."\n";
$var=true; $var=true;
@ -142,42 +143,57 @@ $var=true;
if ($conf->facture->enabled) if ($conf->facture->enabled)
{ {
$var=!$var; $var=!$var;
print "<tr ".$bc[$var].">"; print "<tr ".$bc[$var].">";
print '<td width="60%">'.$langs->trans("DeStockReStockOnBill").'</td>'; print '<td width="60%">'.$langs->trans("DeStockReStockOnBill").'</td>';
print '<td width="160" align="right">'; print '<td width="160" align="right">';
print "<form method=\"post\" action=\"stock.php\">"; print "<form method=\"post\" action=\"stock.php\">";
print "<input type=\"hidden\" name=\"action\" value=\"stock_bill\">"; print "<input type=\"hidden\" name=\"action\" value=\"stock_bill\">";
print $html->selectyesno("stock_bill",$conf->global->STOCK_CALCULATE_ON_BILL,1); print $html->selectyesno("stock_bill",$conf->global->STOCK_CALCULATE_ON_BILL,1);
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">'; print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print "</form>\n</td>\n</tr>\n"; print "</form>\n</td>\n</tr>\n";
} }
if ($conf->commande->enabled) if ($conf->commande->enabled)
{ {
$var=!$var; $var=!$var;
print "<tr ".$bc[$var].">"; print "<tr ".$bc[$var].">";
print '<td width="60%">'.$langs->trans("DeStockReStockOnValidateOrder").'</td>'; print '<td width="60%">'.$langs->trans("DeStockReStockOnValidateOrder").'</td>';
print '<td width="160" align="right">'; print '<td width="160" align="right">';
print "<form method=\"post\" action=\"stock.php\">"; print "<form method=\"post\" action=\"stock.php\">";
print "<input type=\"hidden\" name=\"action\" value=\"stock_validateorder\">"; print "<input type=\"hidden\" name=\"action\" value=\"stock_validateorder\">";
print $html->selectyesno("stock_validateorder",$conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER,1); print $html->selectyesno("stock_validateorder",$conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER,1);
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">'; print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print "</form>\n</td>\n</tr>\n"; print "</form>\n</td>\n</tr>\n";
} }
if ($conf->expedition->enabled) if ($conf->expedition->enabled)
{ {
$var=!$var; $var=!$var;
print "<tr ".$bc[$var].">"; print "<tr ".$bc[$var].">";
print '<td width="60%">'.$langs->trans("DeStockReStockOnShipment").'</td>'; print '<td width="60%">'.$langs->trans("DeStockReStockOnShipment").'</td>';
print '<td width="160" align="right">'; print '<td width="160" align="right">';
print "<form method=\"post\" action=\"stock.php\">"; print "<form method=\"post\" action=\"stock.php\">";
print "<input type=\"hidden\" name=\"action\" value=\"stock_shipment\">"; print "<input type=\"hidden\" name=\"action\" value=\"stock_shipment\">";
print $html->selectyesno("stock_shipment",$conf->global->STOCK_CALCULATE_ON_SHIPMENT,1); print $html->selectyesno("stock_shipment",$conf->global->STOCK_CALCULATE_ON_SHIPMENT,1);
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">'; print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print "</form>\n</td>\n</tr>\n"; print "</form>\n</td>\n</tr>\n";
} }
// Title rule for stock increase
print '<tr class="liste_titre">';
print " <td>".$langs->trans("RuleForStockManagementIncrease")."</td>\n";
print " <td align=\"right\" width=\"160\">".$langs->trans("Value")."</td>\n";
print '</tr>'."\n";
$var=true;
$var=!$var;
print "<tr ".$bc[$var].">";
print '<td colspan="2">'.$langs->trans("FeatureNotYetAvailable").'</td>';
print '</tr>'."\n";
print '</table>'; print '</table>';
$db->close(); $db->close();

View File

@ -52,7 +52,7 @@ class Commande extends CommonObject
var $ref_client; var $ref_client;
var $contactid; var $contactid;
var $projet_id; 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 $facturee;
var $brouillon; var $brouillon;
var $cond_reglement_id; var $cond_reglement_id;
@ -205,6 +205,7 @@ class Commande extends CommonObject
{ {
global $conf,$langs; global $conf,$langs;
// Protection
if ($this->statut == 1) if ($this->statut == 1)
{ {
return 0; return 0;
@ -212,7 +213,7 @@ class Commande extends CommonObject
if (! $user->rights->commande->valider) if (! $user->rights->commande->valider)
{ {
$this->error='Autorisation insuffisante'; $this->error='Permission denied';
return -1; 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) if($conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER == 1)
{ {
require_once(DOL_DOCUMENT_ROOT."/product/stock/mouvementstock.class.php"); require_once(DOL_DOCUMENT_ROOT."/product/stock/mouvementstock.class.php");
for ($i = 0 ; $i < sizeof($this->lignes) ; $i++) 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); $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 $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); $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 * \brief Set draft status
* \param user Object user that modify * \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) function set_draft($user)
{ {
global $conf,$langs; 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 = "UPDATE ".MAIN_DB_PREFIX."commande SET fk_statut = 0";
$sql .= " WHERE rowid = ".$this->id; $sql .= " WHERE rowid = ".$this->id;
dolibarr_syslog("Commande::set_draft sql=".$sql, LOG_DEBUG);
if ($this->db->query($sql)) 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) if ($conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER == 1)
{ {
require_once(DOL_DOCUMENT_ROOT."/product/stock/mouvementstock.class.php"); require_once(DOL_DOCUMENT_ROOT."/product/stock/mouvementstock.class.php");
for ($i = 0 ; $i < sizeof($this->lignes) ; $i++) 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); $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 $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); $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 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 * \brief Cloture la commande
* \param user Objet utilisateur qui cloture * \param user Objet utilisateur qui cloture
* \return int <0 si ko, >0 si ok * \return int <0 if KO, >0 if OK
*/ */
function cloture($user) function cloture($user)
{ {
global $conf; global $conf;
if ($user->rights->commande->valider) if ($user->rights->commande->valider)
{ {
$sql = 'UPDATE '.MAIN_DB_PREFIX.'commande'; $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande';
$sql.= ' SET fk_statut = 3,'; $sql.= ' SET fk_statut = 3,';
$sql.= ' fk_user_cloture = '.$user->id.','; $sql.= ' fk_user_cloture = '.$user->id.',';
$sql.= " date_cloture = ".$this->db->idate(mktime()); $sql.= ' date_cloture = '.$this->db->idate(mktime());
$sql.= " WHERE rowid = $this->id AND fk_statut > 0 ;"; $sql.= ' WHERE rowid = '.$this->id.' AND fk_statut > 0';
if ($this->db->query($sql)) 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; return 1;
} }
else else
{ {
dolibarr_print_error($this->db); $this->error=$this->db->error();
dolibarr_syslog($this->error, LOG_ERR);
return -1; 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) function cancel($user)
{ {
global $conf; global $conf;
if ($user->rights->commande->valider) if ($user->rights->commande->valider)
{ {
$this->db->begin();
$sql = 'UPDATE '.MAIN_DB_PREFIX.'commande SET fk_statut = -1'; $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande SET fk_statut = -1';
$sql .= " WHERE rowid = $this->id AND fk_statut = 1 ;"; $sql .= " WHERE rowid = $this->id AND fk_statut = 1 ;";
if ($this->db->query($sql) ) 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) if($conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER == 1)
{ {
require_once(DOL_DOCUMENT_ROOT."/product/stock/mouvementstock.class.php"); $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);
for ($i = 0 ; $i < sizeof($this->lignes) ; $i++) if ($result > 0)
{ {
if ($conf->global->PRODUIT_SOUSPRODUITS == 1) $this->db->commit();
{ return $result;
$prod = new Product($this->db, $this->lignes[$i]->fk_product); }
$prod -> get_sousproduits_arbo (); else
$prods_arbo = $prod->get_each_prod(); {
if(sizeof($prods_arbo) > 0) $this->error=$mouvP->error;
{ $this->db->rollback();
foreach($prods_arbo as $key => $value) return $result;
{
// 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 1; return 1;
} }
else else
{ {
dolibarr_print_error($this->db); $this->error=$this->db->error();
$this->db->rollback();
dolibarr_syslog($this->error, LOG_ERR);
return -1;
} }
} }
} }
@ -1682,10 +1665,10 @@ class Commande extends CommonObject
// Added by Matelli (See http://matelli.fr/showcases/patchs-dolibarr/add-dates-in-order-lines.html) // 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 // Save the start and end date in the database
if ($date_start) { $sql.= ",date_start='".$date_start."'"; } if ($date_start) { $sql.= ",date_start='".$date_start."'"; }
else { $sql.=',date_start=null'; } else { $sql.=',date_start=null'; }
if ($date_end) { $sql.= ",date_end='".$date_end."'"; } if ($date_end) { $sql.= ",date_end='".$date_end."'"; }
else { $sql.=',date_end=null'; } else { $sql.=',date_end=null'; }
$sql.= " WHERE rowid = ".$rowid; $sql.= " WHERE rowid = ".$rowid;

View File

@ -20,11 +20,11 @@
*/ */
/** /**
\file htdocs/commande/liste.php \file htdocs/commande/liste.php
\ingroup commande \ingroup commande
\brief Page liste des commandes \brief Page liste des commandes
\version $Id$ \version $Id$
*/ */
require('./pre.inc.php'); require('./pre.inc.php');
@ -75,7 +75,7 @@ if (!$user->rights->societe->client->voir && !$socid) $sql .= ", ".MAIN_DB_PREFI
$sql.= ' WHERE c.fk_soc = s.rowid'; $sql.= ' WHERE c.fk_soc = s.rowid';
if (!$user->rights->societe->client->voir && !$socid) //restriction 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) if ($sref)
{ {
@ -147,19 +147,19 @@ if ($resql)
$title = $langs->trans('ListOfOrders'); $title = $langs->trans('ListOfOrders');
} }
if (strval($_GET['viewstatut']) == '0') if (strval($_GET['viewstatut']) == '0')
$title.=' - '.$langs->trans('StatusOrderDraftShort'); $title.=' - '.$langs->trans('StatusOrderDraftShort');
if ($_GET['viewstatut'] == 1) if ($_GET['viewstatut'] == 1)
$title.=' - '.$langs->trans('StatusOrderValidatedShort'); $title.=' - '.$langs->trans('StatusOrderValidatedShort');
if ($_GET['viewstatut'] == 2) if ($_GET['viewstatut'] == 2)
$title.=' - '.$langs->trans('StatusOrderOnProcessShort'); $title.=' - '.$langs->trans('StatusOrderOnProcessShort');
if ($_GET['viewstatut'] == 3) if ($_GET['viewstatut'] == 3)
$title.=' - '.$langs->trans('StatusOrderToBillShort'); $title.=' - '.$langs->trans('StatusOrderToBillShort');
if ($_GET['viewstatut'] == 4) if ($_GET['viewstatut'] == 4)
$title.=' - '.$langs->trans('StatusOrderProcessedShort'); $title.=' - '.$langs->trans('StatusOrderProcessedShort');
if ($_GET['viewstatut'] == -1) if ($_GET['viewstatut'] == -1)
$title.=' - '.$langs->trans('StatusOrderCanceledShort'); $title.=' - '.$langs->trans('StatusOrderCanceledShort');
if ($_GET['viewstatut'] == -2) if ($_GET['viewstatut'] == -2)
$title.=' - '.$langs->trans('StatusOrderToProcessShort'); $title.=' - '.$langs->trans('StatusOrderToProcessShort');
$num = $db->num_rows($resql); $num = $db->num_rows($resql);
print_barre_liste($title, $_GET['page'], 'liste.php','&amp;socid='.$socid.'&amp;viewstatut='.$viewstatut,$sortfield,$sortorder,'',$num); print_barre_liste($title, $_GET['page'], 'liste.php','&amp;socid='.$socid.'&amp;viewstatut='.$viewstatut,$sortfield,$sortorder,'',$num);
@ -193,9 +193,9 @@ if ($resql)
$objp = $db->fetch_object($resql); $objp = $db->fetch_object($resql);
$var=!$var; $var=!$var;
print '<tr '.$bc[$var].'>'; print '<tr '.$bc[$var].'>';
print '<td width="20%" nowrap="nowrap">'; print '<td width="20%" nowrap="nowrap">';
$generic_commande->id=$objp->rowid; $generic_commande->id=$objp->rowid;
$generic_commande->ref=$objp->ref; $generic_commande->ref=$objp->ref;
print '<table class="nobordernopadding"><tr class="nocellnopadd">'; print '<table class="nobordernopadding"><tr class="nocellnopadd">';
@ -217,15 +217,18 @@ if ($resql)
print '</td>'; print '</td>';
print '<td><a href="../comm/fiche.php?socid='.$objp->socid.'">'.img_object($langs->trans('ShowCompany'),'company').' '.$objp->nom.'</a></td>'; print '<td><a href="../comm/fiche.php?socid='.$objp->socid.'">'.img_object($langs->trans('ShowCompany'),'company').' '.$objp->nom.'</a></td>';
print '<td>'.$objp->ref_client.'</td>'; print '<td>'.$objp->ref_client.'</td>';
// 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 '<td align="right">'; print '<td align="right">';
$y = strftime('%Y',$objp->date_commande); print $d;
$m = strftime('%m',$objp->date_commande); print ' <a href="liste.php?year='.$y.'&amp;month='.$m.'">'.$ml.'</a>';
print strftime('%d',$objp->date_commande); print ' <a href="liste.php?year='.$y.'">'.$y.'</a>';
print ' <a href="liste.php?year='.$y.'&amp;month='.$m.'">';
print strftime('%B',$objp->date_commande).'</a>';
print ' <a href="liste.php?year='.$y.'">';
print strftime('%Y',$objp->date_commande).'</a>';
print '</td>'; print '</td>';
print '<td align="right">'.$generic_commande->LibStatut($objp->fk_statut,$objp->facturee,5).'</td>'; print '<td align="right">'.$generic_commande->LibStatut($objp->fk_statut,$objp->facturee,5).'</td>';
print '</tr>'; print '</tr>';

View File

@ -336,11 +336,12 @@ if ($_GET["id"] > 0)
*/ */
print '<table class="liste" width="100%">'; print '<table class="liste" width="100%">';
$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.= " FROM ".MAIN_DB_PREFIX."commandedet as cd";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid";
$sql.= " WHERE cd.fk_commande = ".$commande->id; $sql.= " WHERE cd.fk_commande = ".$commande->id;
// $sql.= " AND p.fk_product_type <> 1"; Why this line ? // $sql.= " AND p.fk_product_type <> 1"; Why this line ?
$sql.= " group by (cd.fk_product)";
$sql.= " ORDER BY cd.rowid"; $sql.= " ORDER BY cd.rowid";
dolibarr_syslog("commande.php sql=".$sql, LOG_DEBUG); dolibarr_syslog("commande.php sql=".$sql, LOG_DEBUG);
@ -390,6 +391,7 @@ if ($_GET["id"] > 0)
print '<td align="center">'.$objp->qty.'</td>'; print '<td align="center">'.$objp->qty.'</td>';
$qtyProdCom=$objp->qty;
print '<td align="center">'; print '<td align="center">';
// Nb of sending products for this line of order // Nb of sending products for this line of order
$quantite_livree = $commande->expeditions[$objp->rowid]; $quantite_livree = $commande->expeditions[$objp->rowid];
@ -418,6 +420,17 @@ if ($_GET["id"] > 0)
} }
print "</tr>"; print "</tr>";
// 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++; $i++;
$var=!$var; $var=!$var;
} }

View File

@ -354,6 +354,7 @@ if ($_GET["action"] == 'create')
} }
print '<td align="center">'.$ligne->qty.'</td>'; print '<td align="center">'.$ligne->qty.'</td>';
$qtyProdCom=$ligne->qty;
print '<td align="center">'; print '<td align="center">';
$quantityDelivered = $object->expeditions[$ligne->id]; $quantityDelivered = $object->expeditions[$ligne->id];
@ -423,6 +424,7 @@ if ($_GET["action"] == 'create')
$html->select_array('entl'.$i,$array,'',1,0,0); $html->select_array('entl'.$i,$array,'',1,0,0);
print '</td>'; print '</td>';
} }
} }
else else
{ {
@ -435,6 +437,17 @@ if ($_GET["action"] == 'create')
print "</tr>\n"; print "</tr>\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++; $indiceAsked++;
} }
@ -448,7 +461,7 @@ if ($_GET["action"] == 'create')
} }
else else
{ {
dolibarr_print_error($db); dolibarr_print_error($db);
} }
} }
} }
@ -506,7 +519,7 @@ else
*/ */
if ($_GET["action"] == 'delete') 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 '<br>'; print '<br>';
} }
@ -516,7 +529,7 @@ else
*/ */
if ($_GET["action"] == 'valid') 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 '<br>'; print '<br>';
} }
/* /*
@ -525,7 +538,7 @@ else
*/ */
if ($_GET["action"] == 'annuler') 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 '<br>'; print '<br>';
} }

View File

@ -99,7 +99,7 @@ MultiPriceLevelsName=Price categories
AssociatedProductsAbility=Activate the associated products AssociatedProductsAbility=Activate the associated products
AssociatedProducts=Associated products AssociatedProducts=Associated products
AssociatedProductsNumber=Number of associated products AssociatedProductsNumber=Number of associated products
EditAssociate=Associated EditAssociate=Associate
Translation=Translation Translation=Translation
KeywordFilter=Keyword filter KeywordFilter=Keyword filter
CategoryFilter=Category filter CategoryFilter=Category filter

View File

@ -35,3 +35,6 @@ Carriers=Carriers
Carrier=Carrier Carrier=Carrier
CarriersArea=Carriers area CarriersArea=Carriers area
NewCarrier=New carrier 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 ?

View File

@ -38,7 +38,8 @@ EnhancedValueOfWarehouses=Warehouses value
UserWarehouseAutoCreate=Create a stock automatically when creating a user UserWarehouseAutoCreate=Create a stock automatically when creating a user
QtyDispatched=Quantity dispatched QtyDispatched=Quantity dispatched
OrderDispatch=Order dispatching 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) 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) 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) DeStockReStockOnShipment=Decrease/increase real stocks on shipment (recommanded)

View File

@ -100,7 +100,7 @@ MultiPriceLevelsName=Categor
AssociatedProductsAbility=Activar productos asociados AssociatedProductsAbility=Activar productos asociados
AssociatedProducts=Productos asociados AssociatedProducts=Productos asociados
AssociatedProductsNumber=Nº de productos asociados AssociatedProductsNumber=Nº de productos asociados
EditAssociate=Asociar a EditAssociate=Asociar
Translation=Traducción Translation=Traducción
KeywordFilter=Filtro por clave KeywordFilter=Filtro por clave
CategoryFilter=Filtro por categoría CategoryFilter=Filtro por categoría

View File

@ -89,7 +89,7 @@ MultiPriceLevelsName=Cat
AssociatedProductsAbility=Activer les produits associés AssociatedProductsAbility=Activer les produits associés
AssociatedProducts=Produits associés AssociatedProducts=Produits associés
AssociatedProductsNumber=Nombre de produits associés AssociatedProductsNumber=Nombre de produits associés
EditAssociate=Associé EditAssociate=Associer
Translation=Traduction Translation=Traduction
KeywordFilter=Filtre par mot-clé KeywordFilter=Filtre par mot-clé
CategoryFilter=Filtre par catégorie CategoryFilter=Filtre par catégorie

View File

@ -74,7 +74,7 @@ NumberOfOrdersByMonth=Nombre de commandes par mois
AmountOfOrdersByMonthHT=Montant total de commandes par mois (HT) AmountOfOrdersByMonthHT=Montant total de commandes par mois (HT)
ListOfOrders=Liste des commandes ListOfOrders=Liste des commandes
CloseOrder=Cloturer commande 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. 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 ? ConfirmDeleteOrder=Êtes-vous sur de vouloir effacer cette commande ?
ConfirmValidateOrder=Êtes-vous sur de vouloir valider cette commande sous la référence <b>%s</b> ? ConfirmValidateOrder=Êtes-vous sur de vouloir valider cette commande sous la référence <b>%s</b> ?

View File

@ -103,7 +103,7 @@ MultiPriceLevelsName=Cat
AssociatedProductsAbility=Prise en charges des produits associés AssociatedProductsAbility=Prise en charges des produits associés
AssociatedProducts=Produits associés AssociatedProducts=Produits associés
AssociatedProductsNumber=Nbre de produits associés AssociatedProductsNumber=Nbre de produits associés
EditAssociate=Associer au EditAssociate=Associer
Translation=Traduction Translation=Traduction
KeywordFilter=Filtre par mot-clé KeywordFilter=Filtre par mot-clé
CategoryFilter=Filtre par catégorie CategoryFilter=Filtre par catégorie

View File

@ -35,3 +35,6 @@ Carriers=Transporteurs
Carrier=Transporteur Carrier=Transporteur
CarriersArea=Espace transporteurs CarriersArea=Espace transporteurs
NewCarrier=Nouveau transporteur 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 ?

View File

@ -38,7 +38,8 @@ EnhancedValueOfWarehouses=Valorisation des stocks
UserWarehouseAutoCreate=Créer un stock automatiquement à la création d'un utilisateur UserWarehouseAutoCreate=Créer un stock automatiquement à la création d'un utilisateur
QtyDispatched=Quantité ventilée QtyDispatched=Quantité ventilée
OrderDispatch=Ventilation commande 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) 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) 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é) DeStockReStockOnShipment=Décrémente/Incrémente les stocks physiques sur les expéditions (recommandé)

View File

@ -38,7 +38,7 @@ EnhancedValueOfWarehouses =Valore magazzini
UserWarehouseAutoCreate =Creare uno stock automaticamente durante la creazione di un utente UserWarehouseAutoCreate =Creare uno stock automaticamente durante la creazione di un utente
QtyDispatched =Quantità spedita QtyDispatched =Quantità spedita
OrderDispatch =Spedizione dell'ordine 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) 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) 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) DeStockReStockOnShipment =Diminuzione / aumento reale delle scorte sulla spedizione (Raccomandato)

View File

@ -220,13 +220,13 @@ class Product extends CommonObject
$sql = "INSERT INTO ".MAIN_DB_PREFIX."product"; $sql = "INSERT INTO ".MAIN_DB_PREFIX."product";
$sql.= " (datec, "; $sql.= " (datec, ";
if ($this->ref) $sql.= "ref, "; if ($this->ref) $sql.= "ref, ";
$sql.= "price_min, price_min_ttc, "; $sql.= "price_min, price_min_ttc, ";
$sql.= "label, "; $sql.= "label, ";
$sql.= "fk_user_author, fk_product_type, price, price_ttc, price_base_type, canvas)"; $sql.= "fk_user_author, fk_product_type, price, price_ttc, price_base_type, canvas)";
$sql.= " VALUES (".$this->db->idate(mktime()).", "; $sql.= " VALUES (".$this->db->idate(mktime()).", ";
if ($this->ref) $sql.= "'".$this->ref."',"; if ($this->ref) $sql.= "'".$this->ref."',";
$sql.= price2num($price_min_ht).","; $sql.= price2num($price_min_ht).",";
$sql.= price2num($price_min_ttc).","; $sql.= price2num($price_min_ttc).",";
$sql.= " ".($this->libelle?"'".addslashes($this->libelle)."'":"null").","; $sql.= " ".($this->libelle?"'".addslashes($this->libelle)."'":"null").",";
$sql.= $user->id.","; $sql.= $user->id.",";
$sql.= " ".$this->type.","; $sql.= " ".$this->type.",";
@ -709,7 +709,7 @@ class Product extends CommonObject
dolibarr_syslog("Product::_log_price sql=".$sql); dolibarr_syslog("Product::_log_price sql=".$sql);
$resql=$this->db->query($sql); $resql=$this->db->query($sql);
if (!$resql) if (!$resql)
$queryError = true; $queryError = true;
if($queryError) if($queryError)
{ {
@ -1043,9 +1043,9 @@ class Product extends CommonObject
} }
} }
} }
$res=$this->load_stock(); $res=$this->load_stock();
return $res; return $res;
} }
@ -1099,7 +1099,7 @@ class Product extends CommonObject
/** /**
* \brief Charge tableau des stats commande client pour le produit/service * \brief Charge tableau des stats commande client pour le produit/service
* \param socid Id societe pour filtrer sur une soci<EFBFBD>t<EFBFBD> * \param socid Id societe pour filtrer sur une societe
* \param filtrestatut Id statut pour filtrer sur un statut * \param filtrestatut Id statut pour filtrer sur un statut
* \return array Tableau des stats * \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 * \brief Charge tableau des stats contrat pour le produit/service
* \param socid Id societe * \param socid Id societe
@ -1810,29 +1854,55 @@ class Product extends CommonObject
$db->commit(); $db->commit();
return 1; return 1;
} }
/** /**
* \brief fonction r<EFBFBD>cursive uniquement utilis<EFBFBD>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 * \return void
*/ */
function fetch_prod_arbo($prod,$compl_path="") function fetch_prod_arbo($prod,$compl_path="",$multiply="")
{ {
global $langs;
$this->res; $this->res;
$this->pere_encours; $this->pere_encours;
foreach($prod as $nom_pere => $desc_pere) foreach($prod as $nom_pere => $desc_pere)
{ {
// on est dans une sous-cat<EFBFBD>gorie // on est dans une sous-categorie
if(is_array($desc_pere)) 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") if($multiply)
$this->res[]= array($compl_path.stripslashes($nom_pere),$desc_pere); {
if(sizeof($desc_pere) >1) $img="";
{ $trueValue=$desc_pere[1]*$multiply;
$this ->fetch_prod_arbo($desc_pere,stripslashes($nom_pere)." -> "); $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("<tr><td>&nbsp; &nbsp; &nbsp;
<a href=\"".DOL_URL_ROOT."/product/fiche.php?id=".$desc_pere[0]."\">".$compl_path.stripslashes($nom_pere)."
</a></td><td align=\"center\"> ".$trueValue."</td><td>&nbsp</td></td><td>&nbsp</td>
</td><td align=\"center\">".$this->stock_entrepot[1]." ".$img."</td></tr>",
$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<EFBFBD>cursive uniquement utilis<EFBFBD>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 * \return void
*/ */
function fetch_prods($prod) function fetch_prods($prod)
@ -1840,34 +1910,35 @@ class Product extends CommonObject
$this->res; $this->res;
foreach($prod as $nom_pere => $desc_pere) foreach($prod as $nom_pere => $desc_pere)
{ {
// on est dans une sous-cat<EFBFBD>gorie // on est dans une sous-categorie
if(is_array($desc_pere)) if(is_array($desc_pere))
$this->res[]= array($desc_pere[1],$desc_pere[0]); $this->res[]= array($desc_pere[1],$desc_pere[0]);
if(sizeof($desc_pere) >1) if(sizeof($desc_pere) >1)
{ {
$this ->fetch_prods($desc_pere); $this ->fetch_prods($desc_pere);
} }
} }
} }
/** /**
* \brief reconstruit l'arborescence des cat<EFBFBD>gorie sous la forme d'un tableau * \brief reconstruit l'arborescence des categorie sous la forme d'un tableau
* \return array $this->res * \return array $this->res
*/ */
function get_arbo_each_prod() function get_arbo_each_prod($multiply="")
{ {
$this->res = array(); $this->res = array();
if(is_array($this -> sousprods)) if(is_array($this -> sousprods))
{ {
foreach($this -> sousprods as $nom_pere => $desc_pere) foreach($this -> sousprods as $nom_pere => $desc_pere)
{ {
if(sizeof($desc_pere) >1) if(sizeof($desc_pere) >1)
$this ->fetch_prod_arbo($desc_pere); $this ->fetch_prod_arbo($desc_pere,"",$multiply);
}
} sort($this->res);
sort($this->res);
} }
return $this->res; return $this->res;
} }
/** /**
* \brief renvoie tous les sousproduits dans le tableau res, chaque ligne de res contient : id -> qty * \brief renvoie tous les sousproduits dans le tableau res, chaque ligne de res contient : id -> qty
* \return array $this->res * \return array $this->res
@ -1878,12 +1949,12 @@ class Product extends CommonObject
if(is_array($this -> sousprods)) if(is_array($this -> sousprods))
{ {
foreach($this -> sousprods as $nom_pere => $desc_pere) foreach($this -> sousprods as $nom_pere => $desc_pere)
{ {
if(sizeof($desc_pere) >1) if(sizeof($desc_pere) >1)
$this ->fetch_prods($desc_pere); $this ->fetch_prods($desc_pere);
} }
sort($this->res); sort($this->res);
} }
return $this->res; return $this->res;
} }

View File

@ -44,13 +44,13 @@ $action=isset($_GET["action"])?$_GET["action"]:$_POST["action"];
$cancel=isset($_GET["cancel"])?$_GET["cancel"]:$_POST["cancel"]; $cancel=isset($_GET["cancel"])?$_GET["cancel"]:$_POST["cancel"];
if ($action <> 're-edit') if ($action <> 're-edit')
{ {
$product = new Product($db); $product = new Product($db);
if ($id) $result = $product->fetch($id); if ($id) $result = $product->fetch($id);
if ($ref) $result = $product->fetch($ref); if ($ref) $result = $product->fetch($ref);
if ($_GET["ref"]) $result = $product->fetch('',$_GET["ref"]); if ($_GET["ref"]) $result = $product->fetch('',$_GET["ref"]);
if ($_GET["id"]) $result = $product->fetch($_GET["id"]); if ($_GET["id"]) $result = $product->fetch($_GET["id"]);
} }
if (!$user->rights->produit->lire) accessforbidden(); if (!$user->rights->produit->lire) accessforbidden();
@ -59,40 +59,40 @@ $html = new Form($db);
// Action association d'un sousproduit // Action association d'un sousproduit
if ($action == 'add_prod' && if ($action == 'add_prod' &&
$cancel <> $langs->trans("Cancel") && $cancel <> $langs->trans("Cancel") &&
$user->rights->produit->creer) $user->rights->produit->creer)
{ {
for($i=0;$i<$_POST["max_prod"];$i++) for($i=0;$i<$_POST["max_prod"];$i++)
{
// print "<br> : ".$_POST["prod_id_chk".$i];
if($_POST["prod_id_chk".$i] != "")
{ {
// print "<br> : ".$_POST["prod_id_chk".$i]; if($product->add_sousproduit($id, $_POST["prod_id_".$i],$_POST["prod_qty_".$i]) > 0)
if($_POST["prod_id_chk".$i] != "") {
{ $action = 'edit';
if($product->add_sousproduit($id, $_POST["prod_id_".$i],$_POST["prod_qty_".$i]) > 0) }
{ else
$action = 'edit'; {
} $action = 're-edit';
else if($product->error == "isFatherOfThis")
{ $mesg = $langs->trans("ErrorAssociationIsFatherOfThis");
$action = 're-edit'; }
if($product->error == "isFatherOfThis") }
$mesg = $langs->trans("ErrorAssociationIsFatherOfThis"); else
} {
} if($product->del_sousproduit($id, $_POST["prod_id_".$i]))
else {
{ $action = 'edit';
if($product->del_sousproduit($id, $_POST["prod_id_".$i])) }
{ else
$action = 'edit'; {
} $action = 're-edit';
else }
{
$action = 're-edit';
}
} }
} }
} }
// action recherche des produits par mot-cle et/ou par categorie // action recherche des produits par mot-cle et/ou par categorie
if($action == 'search' ) 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, p.fk_product_type';
$sql = 'SELECT p.rowid, p.ref, p.label, p.price'; $sql = 'SELECT p.rowid, p.ref, p.label, p.price';
$sql.= ' FROM '.MAIN_DB_PREFIX.'product as p'; $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"; $sql.= " WHERE 1=1";
if($key != "") if($key != "")
{ {
$sql .= " AND (p.ref like '%".$key."%'"; $sql .= " AND (p.ref like '%".$key."%'";
$sql .= " OR p.label 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 .= " ORDER BY p.ref ASC ";
// $sql .= $db->plimit($limit + 1 ,$offset); // $sql .= $db->plimit($limit + 1 ,$offset);
@ -118,9 +118,9 @@ if($action == 'search' )
if ($cancel == $langs->trans("Cancel")) if ($cancel == $langs->trans("Cancel"))
{ {
$action = ''; $action = '';
Header("Location: fiche.php?id=".$_POST["id"]); Header("Location: fiche.php?id=".$_POST["id"]);
exit; exit;
} }
@ -131,6 +131,12 @@ if ($cancel == $langs->trans("Cancel"))
llxHeader("","",$langs->trans("CardProduct".$product->type)); llxHeader("","",$langs->trans("CardProduct".$product->type));
$html = new Form($db); $html = new Form($db);
$productstatic = new Product($db);
if ($mesg) {
print '<br><div class="error">'.$mesg.'</div><br>';
}
$head=product_prepare_head($product, $user); $head=product_prepare_head($product, $user);
$titre=$langs->trans("CardProduct".$product->type); $titre=$langs->trans("CardProduct".$product->type);
dolibarr_fiche_head($head, 'subproduct', $titre); dolibarr_fiche_head($head, 'subproduct', $titre);
@ -141,198 +147,190 @@ dolibarr_fiche_head($head, 'subproduct', $titre);
if ($id || $ref) if ($id || $ref)
{ {
if ( $result )
{
if ($action <> 'edit' &&$action <> 'search' && $action <> 're-edit') if ( $result )
{ {
/*
* En mode visu
*/
print($mesg); if ($action <> 'edit' &&$action <> 'search' && $action <> 're-edit')
print '<table class="border" width="100%">';
print "<tr>";
$nblignes=6;
if ($product->isproduct() && $conf->stock->enabled) $nblignes++;
if ($product->isservice()) $nblignes++;
// Reference
print '<td width="15%">'.$langs->trans("Ref").'</td><td>';
print $html->showrefnav($product,'ref','',1,'ref');
print '</td></tr>';
// Libelle
print '<tr><td>'.$langs->trans("Label").'</td><td>'.$product->libelle.'</td>';
print '</tr>';
$product->get_sousproduits_arbo ();
print '<tr><td>'.$langs->trans("AssociatedProductsNumber").'</td><td>'.sizeof($product->get_arbo_each_prod()).'</td>';
// associations sousproduits
$prods_arbo = $product->get_arbo_each_prod();
if(sizeof($prods_arbo) > 0)
{
print '<tr><td colspan="2">';
print '<b>'.$langs->trans("ProductAssociationList").'</b><br>';
foreach($prods_arbo as $key => $value)
{ {
print '- <a href="'.DOL_URL_ROOT.'/product/fiche.php?id='.$value[1].'">'.$value[0].'</a><br>'; /*
* En mode visu
*/
print '<table class="border" width="100%">';
print "<tr>";
$nblignes=6;
if ($product->isproduct() && $conf->stock->enabled) $nblignes++;
if ($product->isservice()) $nblignes++;
// Reference
print '<td width="25%">'.$langs->trans("Ref").'</td><td>';
print $html->showrefnav($product,'ref','',1,'ref');
print '</td></tr>';
// Libelle
print '<tr><td>'.$langs->trans("Label").'</td><td>'.$product->libelle.'</td>';
print '</tr>';
$product->get_sousproduits_arbo ();
print '<tr><td>'.$langs->trans("AssociatedProductsNumber").'</td><td>'.sizeof($product->get_arbo_each_prod()).'</td>';
// associations sousproduits
$prods_arbo = $product->get_arbo_each_prod();
if(sizeof($prods_arbo) > 0)
{
print '<tr><td colspan="2">';
print '<b>'.$langs->trans("ProductAssociationList").'</b><br>';
foreach($prods_arbo as $key => $value)
{
$productstatic->id=$value[1];
$productstatic->type=0;
$productstatic->ref=$value[0];
print $productstatic->getNomUrl(1).'<br>';
}
print '</td></tr>';
}
print "</table>\n";
print "</div>\n";
}
}
/*
* Fiche en mode edition
*/
if (($action == 'edit' || $action == 'search' || $action == 're-edit') && $user->rights->produit->creer)
{
print '<table class="border" width="100%">';
print "<tr>";
$nblignes=6;
if ($product->isproduct() && $conf->stock->enabled) $nblignes++;
if ($product->isservice()) $nblignes++;
// Reference
print '<td width="25%">'.$langs->trans("Ref").'</td><td>';
print $html->showrefnav($product,'ref','',1,'ref');
print '</td></tr>';
if ($product->is_photo_available($conf->produit->dir_output))
{
// Photo
print '<td valign="middle" align="center" rowspan="'.$nblignes.'">';
$nbphoto=$product->show_photos($conf->produit->dir_output,1,1,0);
print '</td>';
} }
print '</tr>';
print '</td></tr>'; // Libelle
} print '<tr><td>'.$langs->trans("Label").'</td><td>'.$product->libelle.'</td>';
print '</tr>';
// Nombre de sousproduits associes
$product->get_sousproduits_arbo ();
print '<tr><td>'.$langs->trans("AssociatedProductsNumber").'</td><td>'.sizeof($product->get_arbo_each_prod()).'</td>';
print '</tr>';
print '<tr><td colspan="2"><b>'.$langs->trans("ProductToAddSearch").'</b>';
print '<table class="noborder">';
print '<tr><td><form action="'.DOL_URL_ROOT.'/product/sousproduits/fiche.php?id='.$id.'" method="post">';
print $langs->trans("KeywordFilter");
print '</td><td><input type="text" name="key" value="'.$key.'">';
print '<input type="hidden" name="action" value="search">';
print '<input type="hidden" name="id" value="'.$id.'">';
print '</td></tr>';
print "</table>\n"; if($conf->categorie->enabled)
{
print '<tr><td>'.$langs->trans("CategoryFilter");
print '</td><td>'.$html->select_all_categories(0,$catMere).'</td></tr>';
}
print "</div>\n"; print '<tr><td colspan="2"><input type="submit" class="button" value="'.$langs->trans("Search").'"></td></tr>';
} print '</form>';
} print '<tr><td colspan="2"><br>';
/* if($action == 'search')
* Fiche en mode edition {
*/ print '<table class="border">';
if (($action == 'edit' || $action == 'search' || $action == 're-edit') && $user->rights->produit->creer) print '<tr>';
{ print '<td><b>'.$langs->trans("Ref").'</b></td><td><b>'.$langs->trans("Label").'</b></td><td><b>'.$langs->trans("AddDel").'</b></td><td><b>'.$langs->trans("Quantity").'</b></td>';
print '<form action="'.DOL_URL_ROOT.'/product/sousproduits/fiche.php?id='.$id.'" method="post">';
if ($product->isservice()) { print '<input type="hidden" name="action" value="add_prod"';
print_fiche_titre($langs->trans('EditAssociate').' '.$langs->trans('Service').' : '.$product->ref, ""); print '<input type="hidden" name="id" value="'.$id.'"';
} else { if ($resql)
print_fiche_titre($langs->trans('EditAssociate').' '.$langs->trans('Product').' : '.$product->ref, "");
}
if ($mesg) {
print '<br><div class="error">'.$mesg.'</div><br>';
}
print '<table class="border" width="100%">';
print "<tr>";
$nblignes=6;
if ($product->isproduct() && $conf->stock->enabled) $nblignes++;
if ($product->isservice()) $nblignes++;
// Reference
print '<td width="15%">'.$langs->trans("Ref").'</td><td>';
print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$product->id.'">'.$product->ref.'</a>';
print '</td>';
if ($product->is_photo_available($conf->produit->dir_output))
{
// Photo
print '<td valign="middle" align="center" rowspan="'.$nblignes.'">';
$nbphoto=$product->show_photos($conf->produit->dir_output,1,1,0);
print '</td>';
}
print '</tr>';
// Libelle
print '<tr><td>'.$langs->trans("Label").'</td><td>'.$product->libelle.'</td>';
print '</tr>';
// Nombre de sousproduits associ<63>s
$product->get_sousproduits_arbo ();
print '<tr><td>'.$langs->trans("AssociatedProductsNumber").'</td><td>'.sizeof($product->get_arbo_each_prod()).'</td>';
print '</tr>';
print '<tr><td colspan="2"><b>'.$langs->trans("ProductToAddSearch").'</b>';
print '<table class="noborder">';
print '<tr><td><form action="'.DOL_URL_ROOT.'/product/sousproduits/fiche.php?id='.$id.'" method="post">';
print $langs->trans("KeywordFilter");
print '</td><td><input type="text" name="key" value="'.$key.'">';
print '<input type="hidden" name="action" value="search">';
print '<input type="hidden" name="id" value="'.$id.'">';
print '</td></tr>';
if($conf->categorie->enabled)
{ {
print '<tr><td>'.$langs->trans("CategoryFilter"); $num = $db->num_rows($resql);
print '</td><td>'.$html->select_all_categories(0,$catMere).'</td></tr>'; $i=0;
} if($num == 0)
print '<tr><td colspan="4">'.$langs->trans("NoMatchFound").'</td></tr>';
print '<tr><td colspan="2"><input type="submit" class="button" value="'.$langs->trans("Search").'"></td></tr>'; while ($i < $num)
print '</form>';
print '<tr><td colspan="2"><br>';
if($action == 'search')
{
print '<table class="border">';
print '<tr>';
print '<td><b>'.$langs->trans("Ref").'</b></td><td><b>'.$langs->trans("Label").'</b></td><td><b>'.$langs->trans("AddDel").'</b></td><td><b>'.$langs->trans("Quantity").'</b></td>';
print '<form action="'.DOL_URL_ROOT.'/product/sousproduits/fiche.php?id='.$id.'" method="post">';
print '<input type="hidden" name="action" value="add_prod"';
print '<input type="hidden" name="id" value="'.$id.'"';
if ($resql)
{ {
$num = $db->num_rows($resql); $objp = $db->fetch_object($resql);
$i=0; if($objp->rowid != $id)
if($num == 0)
print '<tr><td colspan="4">'.$langs->trans("NoMatchFound").'</td></tr>';
while ($i < $num)
{ {
$objp = $db->fetch_object($resql); // check if a product is not already a parent product of this one
if($objp->rowid != $id) $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 $is_pere=0;
$prod_arbo=new Product($db,$objp->rowid); $prod_arbo->get_sousproduits_arbo ();
if ($prod_arbo->type==2 || $prod_arbo->type==3) { // associations sousproduits
$is_pere=0; $prods_arbo = $prod_arbo->get_arbo_each_prod();
$prod_arbo->get_sousproduits_arbo (); if(sizeof($prods_arbo) > 0) {
// associations sousproduits foreach($prods_arbo as $key => $value) {
$prods_arbo = $prod_arbo->get_arbo_each_prod(); if ($value[1]==$id) {
if(sizeof($prods_arbo) > 0) { $is_pere=1;
foreach($prods_arbo as $key => $value) { }
if ($value[1]==$id) { }
$is_pere=1;
}
}
}
if ($is_pere==1) {
$i++;
continue;
}
}
print "\n<tr>";
print '<td>'.$objp->ref.'</td>';
print '<td>'.$objp->label.'</td>';
if($product->is_sousproduit($id, $objp->rowid))
{
$addchecked = ' checked="true"';
$qty=$product->is_sousproduit_qty;
} }
else if ($is_pere==1) {
{ $i++;
$addchecked = ''; continue;
$qty="1";
} }
print '<td align="center"><input type="hidden" name="prod_id_'.$i.'" value="'.$objp->rowid.'">';
print '<input type="checkbox" '.$addchecked.'name="prod_id_chk'.$i.'" value="'.$objp->rowid.'"></td>';
print '<td align="center"><input type="text" size="3" name="prod_qty_'.$i.'" value="'.$qty.'"></td>';
print '</td>';
print '</tr>';
} }
$i++; print "\n<tr>";
print '<td>'.$objp->ref.'</td>';
print '<td>'.$objp->label.'</td>';
if($product->is_sousproduit($id, $objp->rowid))
{
$addchecked = ' checked="true"';
$qty=$product->is_sousproduit_qty;
}
else
{
$addchecked = '';
$qty="1";
}
print '<td align="center"><input type="hidden" name="prod_id_'.$i.'" value="'.$objp->rowid.'">';
print '<input type="checkbox" '.$addchecked.'name="prod_id_chk'.$i.'" value="'.$objp->rowid.'"></td>';
print '<td align="center"><input type="text" size="3" name="prod_qty_'.$i.'" value="'.$qty.'"></td>';
print '</td>';
print '</tr>';
} }
$i++;
}
}
else
{
dolibarr_print_error($db);
}
print '<input type="hidden" name="max_prod" value="'.$i.'">';
if($num > 0)
print '<tr><td colspan="2"><input type="submit" class="button" value="'.$langs->trans("Update").'"></td></tr>';
print '</table>';
} }
else
{
dolibarr_print_error($db);
}
print '<input type="hidden" name="max_prod" value="'.$i.'">';
if($num > 0)
print '<tr><td colspan="2"><input type="submit" class="button" value="'.$langs->trans("Update").'"></td></tr>';
print '</table>';
}
print '</form></td></tr>'; print '</form></td></tr>';
print '</td></tr>'; print '</td></tr>';
print '</table>'; print '</table>';
} }
} }
@ -347,11 +345,11 @@ print "\n<div class=\"tabsAction\">\n";
if ($action == '') if ($action == '')
{ {
if ( $user->rights->produit->creer) if ( $user->rights->produit->creer)
{ {
print '<a class="butAction" href="'.DOL_URL_ROOT.'/product/sousproduits/fiche.php?action=edit&amp;id='.$product->id.'">'.$langs->trans("Modify").'</a>'; print '<a class="butAction" href="'.DOL_URL_ROOT.'/product/sousproduits/fiche.php?action=edit&amp;id='.$product->id.'">'.$langs->trans("EditAssociate").'</a>';
} }
} }

View File

@ -21,390 +21,422 @@
*/ */
/** /**
\file htdocs/product/stock/mouvementstock.class.php \file htdocs/product/stock/mouvementstock.class.php
\ingroup stock \ingroup stock
\brief Fichier de la classe de gestion des mouvements de stocks \brief Fichier de la classe de gestion des mouvements de stocks
\version $Revision$ \version $Revision$
*/ */
/** /**
\class MouvementStock \class MouvementStock
\brief Classe permettant la gestion des mouvements de stocks \brief Classe permettant la gestion des mouvements de stocks
*/ */
class MouvementStock class MouvementStock
{ {
function MouvementStock($DB) 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 )
{ {
$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; $entrepot_value_pmp = 0;
if ($error === 0) if ($error === 0)
{ {
$sql = "SELECT valo_pmp,".$this->db->pdate("date_calcul")." FROM ".MAIN_DB_PREFIX."entrepot_valorisation"; $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;"; $sql.= " WHERE fk_entrepot = $entrepot_id ORDER BY date_calcul DESC LIMIT 1;";
if ($this->db->query($sql)) if ($this->db->query($sql))
{ {
while ($row = $this->db->fetch_row($resql) ) while ($row = $this->db->fetch_row($resql) )
{ {
$entrepot_value_pmp = $row[0]; $entrepot_value_pmp = $row[0];
$entrepot_value_date = $row[1]; $entrepot_value_date = $row[1];
} }
$this->db->free($resql); $this->db->free($resql);
} }
else else
{ {
$error = -26; $error = -26;
dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]"); dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]");
} }
} }
$new_value = $entrepot_value_pmp + $valo_mouvement; $new_value = $entrepot_value_pmp + $valo_mouvement;
$now = time(); $now = time();
if ($error === 0) if ($error === 0)
{ {
if ( strftime('%Y%m%d',$entrepot_value_date) == strftime('%Y%m%d',$now) ) if ( strftime('%Y%m%d',$entrepot_value_date) == strftime('%Y%m%d',$now) )
{ {
$sql = "UPDATE ".MAIN_DB_PREFIX."entrepot_valorisation"; $sql = "UPDATE ".MAIN_DB_PREFIX."entrepot_valorisation";
$sql.= " SET valo_pmp='".ereg_replace(",",".",$new_value)."'"; $sql.= " SET valo_pmp='".ereg_replace(",",".",$new_value)."'";
$sql.= " WHERE fk_entrepot = $entrepot_id "; $sql.= " WHERE fk_entrepot = $entrepot_id ";
$sql.= " AND ".$this->db->pdate("date_calcul")."='".$entrepot_value_date."';"; $sql.= " AND ".$this->db->pdate("date_calcul")."='".$entrepot_value_date."';";
} }
else else
{ {
$sql = "INSERT INTO ".MAIN_DB_PREFIX."entrepot_valorisation"; $sql = "INSERT INTO ".MAIN_DB_PREFIX."entrepot_valorisation";
$sql.= " (date_calcul, fk_entrepot, valo_pmp)"; $sql.= " (date_calcul, fk_entrepot, valo_pmp)";
$sql.= " VALUES (".$this->db->idate(mktime()).", ".$entrepot_id; $sql.= " VALUES (".$this->db->idate(mktime()).", ".$entrepot_id;
$sql.= ",'".ereg_replace(",",".",$new_value)."');"; $sql.= ",'".ereg_replace(",",".",$new_value)."');";
} }
if ($this->db->query($sql)) if ($this->db->query($sql))
{ {
} }
else else
{ {
$error = -27; $error = -27;
dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]"); dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]");
} }
} }
if ($error === 0) if ($error === 0)
{ {
$sql = "UPDATE ".MAIN_DB_PREFIX."entrepot"; $sql = "UPDATE ".MAIN_DB_PREFIX."entrepot";
$sql.= " SET valo_pmp='".ereg_replace(",",".",$new_value)."'"; $sql.= " SET valo_pmp='".ereg_replace(",",".",$new_value)."'";
$sql.= " WHERE rowid = $entrepot_id "; $sql.= " WHERE rowid = $entrepot_id ";
if ($this->db->query($sql)) if ($this->db->query($sql))
{ {
} }
else else
{ {
$error = -28; $error = -28;
dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]"); dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp ERRORSQL[$error]");
} }
} }
if ($error === 0) if ($error === 0)
{ {
return 0; return 0;
} }
else else
{ {
dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp RETURN IN ERROR[$error]"); dolibarr_syslog("MouvementStock::CalculateEntrepotValoPmp RETURN IN ERROR[$error]");
return $error; return $error;
} }
} }
else else
{ {
return 0; return 0;
}
} }
}
/** /**
* \brief ??? * \brief ???
* \param mvid int Id du mouvement * \param mvid int Id du mouvement
* \param fk_product int Id produit * \param fk_product int Id produit
* \param qty float Quantité * \param qty float Quantité
* \param price float Prix unitaire du produit * \param price float Prix unitaire du produit
* \param value_ope float Valeur du mouvement en retour * \param value_ope float Valeur du mouvement en retour
* \return int <0 si ko, 0 si ok * \return int <0 si ko, 0 si ok
*/ */
function CalculateValoPmp($mvid, $fk_product, $qty, $price=0, &$value_ope) function CalculateValoPmp($mvid, $fk_product, $qty, $price=0, &$value_ope)
{
$error = 0;
dolibarr_syslog("MouvementStock::CalculateValoPmp $mvid, $fk_product, $qty, $price");
if ( $qty <> 0 )
{ {
$price_pmp = 0; $error = 0;
$qty_stock = 0; dolibarr_syslog("MouvementStock::CalculateValoPmp $mvid, $fk_product, $qty, $price");
$stock_value_pmp = 0;
if ($error === 0) if ( $qty <> 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 = 0;
{ $qty_stock = 0;
$price_pmp = $row[0]; $stock_value_pmp = 0;
$qty_stock = $row[1];
$stock_value_pmp = $row[2]; if ($error === 0)
} {
$this->db->free($resql); $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 else
{ {
dolibarr_syslog("MouvementStock::CalculateValoPmp ERRORSQL[1] ".$this->error); return 0;
$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
/**
* \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 livraison($user, $fk_product, $entrepot_id, $qty) function reception($user, $fk_product, $entrepot_id, $qty, $price=0)
{ {
return $this->_create($user, $fk_product, $entrepot_id, (0 - $qty), 2); return $this->_create($user, $fk_product, $entrepot_id, $qty, 3, $price);
} }
/* /**
* * Return nb of subproducts for a product
* *
*/ * @param unknown_type $id
function reception($user, $fk_product, $entrepot_id, $qty, $price=0) * @return unknown
{ */
return $this->_create($user, $fk_product, $entrepot_id, $qty, 3, $price); 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;
}
} }
?> ?>

View File

@ -147,15 +147,14 @@ if ($_GET["id"] || $_GET["ref"])
print '<td>'.$product->stock_reel.'</td>'; print '<td>'.$product->stock_reel.'</td>';
print '</tr>'; print '</tr>';
// Calculating a theorical value of stock if stock increment is done on real sending
// Calculating a theorical value of stock if stock increment is done on order if ($conf->global->STOCK_CALCULATE_ON_SHIPMENT)
if ($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER)
{ {
$stock_commande_client=$stock_commande_fournisseur=0; $stock_commande_client=$stock_commande_fournisseur=0;
if ($conf->commande->enabled) 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); if ($result < 0) dolibarr_print_error($db,$product->error);
$stock_commande_client=$product->stats_commande['qty']; $stock_commande_client=$product->stats_commande['qty'];
} }
@ -166,7 +165,7 @@ if ($_GET["id"] || $_GET["ref"])
$stock_commande_fournisseur=$product->stats_commande_fournisseur['qty']; $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 // Stock theorique
print '<tr><td>'.$langs->trans("VirtualStock").'</td>'; print '<tr><td>'.$langs->trans("VirtualStock").'</td>';
@ -190,10 +189,12 @@ if ($_GET["id"] || $_GET["ref"])
if ($conf->commande->enabled) if ($conf->commande->enabled)
{ {
if ($found) print '<br>'; else $found=1; if ($found) print '<br>'; else $found=1;
print $langs->trans("CustomersOrdersRunning").': '.$stock_commande_client; print $langs->trans("CustomersOrdersRunning").': '.($stock_commande_client+$stock_sending_client);
$result=$product->load_stats_commande(0,'0,1'); $result=$product->load_stats_commande(0,'0');
if ($result < 0) dolibarr_print_error($db,$product->error); 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 '<br>';
//print $langs->trans("CustomersSendingRunning").': '.$stock_sending_client;
} }
// Nbre de commande fournisseurs en cours // Nbre de commande fournisseurs en cours