From c89c89c73ef1ed34e25e4bc316bce936f0578e55 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur <eldy@destailleur.fr>
Date: Mon, 4 May 2015 22:02:54 +0200
Subject: [PATCH] Mutualise code and some fixes for stock management.

---
 htdocs/core/class/html.form.class.php         |  11 +-
 htdocs/core/class/html.formmail.class.php     |  28 +--
 htdocs/product/stock/card.php                 |   6 +-
 htdocs/product/stock/class/entrepot.class.php |   2 +-
 htdocs/product/stock/mouvement.php            | 100 ++++++++---
 htdocs/product/stock/product.php              | 166 +-----------------
 .../product/stock/tpl/stockcorrection.tpl.php | 119 +++++++++++++
 .../product/stock/tpl/stocktransfer.tpl.php   | 107 +++++++++++
 htdocs/societe/soc.php                        |  10 +-
 9 files changed, 343 insertions(+), 206 deletions(-)
 create mode 100644 htdocs/product/stock/tpl/stockcorrection.tpl.php
 create mode 100644 htdocs/product/stock/tpl/stocktransfer.tpl.php

diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index 82364874cfe..f80fdd87304 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -1493,13 +1493,13 @@ class Form
      *  @param		int			$price_level			Level of price to show
      *  @param		int			$status					-1=Return all products, 0=Products not on sell, 1=Products on sell
      *  @param		int			$finished				2=all, 1=finished, 0=raw material
-     *  @param		string		$selected_input_value	Value of preselected input text (with ajax)
+     *  @param		string		$selected_input_value	Value of preselected input text (for use with ajax)
      *  @param		int			$hidelabel				Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after)
      *  @param		array		$ajaxoptions			Options for ajax_autocompleter
      *  @param      int			$socid					Thirdparty Id
      *  @return		void
      */
-    function select_produits($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(),$socid=0)
+    function select_produits($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(), $socid=0)
     {
         global $langs,$conf;
 
@@ -1512,9 +1512,10 @@ class Form
             if ($selected && empty($selected_input_value))
             {
                 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
-                $product = new Product($this->db);
-                $product->fetch($selected);
-                $selected_input_value=$product->ref;
+                $producttmpselect = new Product($this->db);
+                $producttmpselect->fetch($selected);
+                $selected_input_value=$producttmpselect->ref;
+                unset($producttmpselect);
             }
             // mode=1 means customers products
             $urloption='htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&finished='.$finished;
diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php
index 3c799b767af..b9d5048db74 100644
--- a/htdocs/core/class/html.formmail.class.php
+++ b/htdocs/core/class/html.formmail.class.php
@@ -44,6 +44,7 @@ class FormMail extends Form
     var $replytomail;
     var $toname;
     var $tomail;
+	var $trackid;
 
     var $withsubstit;			// Show substitution array
     var $withfrom;
@@ -244,7 +245,7 @@ class FormMail extends Form
         else
         {
         	$out='';
-        	
+
         	// Define list of attached files
         	$listofpaths=array();
         	$listofnames=array();
@@ -277,12 +278,13 @@ class FormMail extends Form
         		$out.= '<form method="POST" name="mailform" enctype="multipart/form-data" action="'.$this->param["returnurl"].'">'."\n";
 				$out.= '<input style="display:none" type="submit" id="sendmail" name="sendmail">';
         		$out.= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'" />';
+        		$out.= '<input type="hidden" name="trackid" value="'.$this->trackid.'" />';
         	}
         	foreach ($this->param as $key=>$value)
         	{
         		$out.= '<input type="hidden" id="'.$key.'" name="'.$key.'" value="'.$value.'" />'."\n";
         	}
-        	
+
         	$result = $this->fetchAllEMailTemplate($this->param["models"], $user, $outputlangs);
         	if ($result<0) {
         		setEventMessage($this->error,'errors');
@@ -291,7 +293,7 @@ class FormMail extends Form
         	foreach($this->lines_model as $line) {
         		$modelmail_array[$line->id]=$line->label;
         	}
-        	
+
         	if (count($modelmail_array)>0) {
 	        	$out.= '<table class="nobordernopadding" width="100%"><tr><td width="20%">'."\n";
 	        	$out.= $langs->trans('SelectMailModel').':'.$this->selectarray('modelmailselected', $modelmail_array,$model_id);
@@ -302,8 +304,8 @@ class FormMail extends Form
 	        	$out.= '<td><input class="flat" type="submit" value="'.$langs->trans('Valid').'" name="modelselected" id="modelselected"></td>';
 	        	$out.= '</tr></table>';
         	}
-        	
-        	
+
+
         	$out.= '<table class="border" width="100%">'."\n";
 
         	// Substitution array
@@ -644,7 +646,7 @@ class FormMail extends Form
 					$defaultmessage = dol_nl2br($defaultmessage);
 				}
 
-				
+
         		if (isset($_POST["message"]) &&  ! $_POST['modelselected']) $defaultmessage=$_POST["message"];
 				else
 				{
@@ -774,7 +776,7 @@ class FormMail extends Form
 			return -1;
 		}
 	}
-	
+
 	/**
 	 *      Find if template exists
 	 *      Search into table c_email_templates
@@ -787,7 +789,7 @@ class FormMail extends Form
 	public function isEMailTemplate($type_template, $user, $outputlangs)
 	{
 		$ret=array();
-	
+
 		$sql = "SELECT label, topic, content, lang";
 		$sql.= " FROM ".MAIN_DB_PREFIX.'c_email_templates';
 		$sql.= " WHERE type_template='".$this->db->escape($type_template)."'";
@@ -796,7 +798,7 @@ class FormMail extends Form
 		if (is_object($outputlangs)) $sql.= " AND (lang = '".$outputlangs->defaultlang."' OR lang IS NULL OR lang = '')";
 		$sql.= $this->db->order("lang,label","ASC");
 		//print $sql;
-	
+
 		$resql = $this->db->query($sql);
 		if ($resql)
 		{
@@ -810,7 +812,7 @@ class FormMail extends Form
 			return -1;
 		}
 	}
-	
+
 	/**
 	 *      Find if template exists
 	 *      Search into table c_email_templates
@@ -823,7 +825,7 @@ class FormMail extends Form
 	public function fetchAllEMailTemplate($type_template, $user, $outputlangs)
 	{
 		$ret=array();
-	
+
 		$sql = "SELECT rowid, label, topic, content, lang";
 		$sql.= " FROM ".MAIN_DB_PREFIX.'c_email_templates';
 		$sql.= " WHERE type_template='".$this->db->escape($type_template)."'";
@@ -832,12 +834,12 @@ class FormMail extends Form
 		if (is_object($outputlangs)) $sql.= " AND (lang = '".$outputlangs->defaultlang."' OR lang IS NULL OR lang = '')";
 		$sql.= $this->db->order("lang,label","ASC");
 		//print $sql;
-	
+
 		$resql = $this->db->query($sql);
 		if ($resql)
 		{
 			$this->lines_model=array();
-			while ($obj = $this->db->fetch_object($resql)) 
+			while ($obj = $this->db->fetch_object($resql))
 			{
 				$line = new ModelMail();
 				$line->id=$obj->rowid;
diff --git a/htdocs/product/stock/card.php b/htdocs/product/stock/card.php
index 8d9ee5b6d64..37f39010659 100644
--- a/htdocs/product/stock/card.php
+++ b/htdocs/product/stock/card.php
@@ -308,7 +308,7 @@ else
 
 			// Value
 			print '<tr><td valign="top">'.$langs->trans("EstimatedStockValueShort").'</td><td colspan="3">';
-			print empty($calcproducts['value'])?'0':$calcproducts['value'];
+			print price((empty($calcproducts['value'])?'0':price2num($calcproducts['value'],'MT')), 0, $langs, 0, -1, -1, $conf->currency);
 			print "</td></tr>";
 
 			// Last movement
@@ -387,8 +387,8 @@ else
 			print_liste_field_titre($langs->trans("EstimatedStockValueShort"),"", "","&amp;id=".$id,"",'align="right"',$sortfield,$sortorder);
             if (empty($conf->global->PRODUIT_MULTIPRICES)) print_liste_field_titre($langs->trans("SellPriceMin"),"", "p.price","&amp;id=".$id,"",'align="right"',$sortfield,$sortorder);
             if (empty($conf->global->PRODUIT_MULTIPRICES)) print_liste_field_titre($langs->trans("EstimatedStockValueSellShort"),"", "","&amp;id=".$id,"",'align="right"',$sortfield,$sortorder);
-			if ($user->rights->stock->mouvement->creer) print '<td>&nbsp;</td>';
-			if ($user->rights->stock->creer)            print '<td>&nbsp;</td>';
+			if ($user->rights->stock->mouvement->creer) print_liste_field_titre('');
+			if ($user->rights->stock->creer)            print_liste_field_titre('');
 			print "</tr>";
 
 			$totalunit=0;
diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php
index 271da598b6b..5a8050612e4 100644
--- a/htdocs/product/stock/class/entrepot.class.php
+++ b/htdocs/product/stock/class/entrepot.class.php
@@ -415,7 +415,7 @@ class Entrepot extends CommonObject
 	{
 		$ret=array();
 
-		$sql = "SELECT sum(ps.reel) as nb, sum(ps.reel * ps.pmp) as value";
+		$sql = "SELECT sum(ps.reel) as nb, sum(ps.reel * p.pmp) as value";
 		$sql.= " FROM ".MAIN_DB_PREFIX."product_stock as ps";
 		$sql.= ", ".MAIN_DB_PREFIX."product as p";
 		$sql.= " WHERE ps.fk_entrepot = ".$this->id;
diff --git a/htdocs/product/stock/mouvement.php b/htdocs/product/stock/mouvement.php
index 51c0f0a6113..2a08eb6a7df 100644
--- a/htdocs/product/stock/mouvement.php
+++ b/htdocs/product/stock/mouvement.php
@@ -86,27 +86,69 @@ if ($cancel) $action='';	// Protection to avoid action for all cancel buttons
 // Correct stock
 if ($action == "correct_stock")
 {
-    if (is_numeric($_POST["nbpiece"]) && $product_id)
-    {
-        $product = new Product($db);
-        $result=$product->fetch($product_id);
+	$product = new Product($db);
+	if (! empty($product_id)) $result=$product->fetch($product_id);
+
+	$error=0;
+
+	if (empty($product_id))
+	{
+		$error++;
+		setEventMessage($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Product")), 'errors');
+		$action='correction';
+	}
+	if (! is_numeric($_POST["nbpiece"]))
+	{
+		$error++;
+		setEventMessage($langs->trans("ErrorFieldMustBeANumeric", $langs->transnoentitiesnoconv("NumberOfUnit")), 'errors');
+		$action='correction';
+	}
 
-        $result=$product->correct_stock(
-            $user,
-            $id,
-            $_POST["nbpiece"],
-            $_POST["mouvement"],
-            $_POST["label"],
-            0
-        );		// We do not change value of stock for a correction
+	if (! $error)
+    {
+        if ($product->hasbatch())
+        {
+        	$batch=GETPOST('batch_number');
+        	$eatby=GETPOST('eatby');
+        	$sellby=GETPOST('sellby');
+	        $result=$product->correct_stock_batch(
+	            $user,
+	            $id,
+	            GETPOST("nbpiece",'int'),
+	            GETPOST("mouvement"),
+	            GETPOST("label",'san_alpha'),
+	            GETPOST('unitprice'),
+	        	$eatby,$sellby,$batch,
+	        	GETPOST('inventorycode')
+	        );		// We do not change value of stock for a correction
+        }
+        else
+		{
+	        $result=$product->correct_stock(
+	            $user,
+	            $id,
+	            GETPOST("nbpiece",'int'),
+	            GETPOST("mouvement"),
+	            GETPOST("label",'san_alpha'),
+	            GETPOST('unitprice'),
+	        	GETPOST('inventorycode')
+	        );		// We do not change value of stock for a correction
+        }
 
         if ($result > 0)
         {
             header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
             exit;
         }
+        else
+       {
+       		$error++;
+        	setEventMessages($product->error, $product->errors, 'errors');
+        	$action='correction';
+       }
     }
-    else $action='';
+
+    if (! $error) $action='';
 }
 
 
@@ -165,6 +207,7 @@ $sql.= $db->order($sortfield,$sortorder);
 $sql.= $db->plimit($conf->liste_limit+1, $offset);
 
 //print $sql;
+
 $resql = $db->query($sql);
 if ($resql)
 {
@@ -254,7 +297,7 @@ if ($resql)
 
         // Value
         print '<tr><td valign="top">'.$langs->trans("EstimatedStockValueShort").'</td><td colspan="3">';
-        print empty($calcproducts['value'])?'0':$calcproducts['value'];
+        print price((empty($calcproducts['value'])?'0':price2num($calcproducts['value'],'MT')), 0, $langs, 0, -1, -1, $conf->currency);
         print "</td></tr>";
 
         // Last movement
@@ -285,13 +328,34 @@ if ($resql)
 
         print "</table>";
 
-        print '</div>';
+        dol_fiche_end();
     }
 
 
+	/*
+	 * Correct stock
+	 */
+	if ($action == "correction")
+	{
+		if ($id) $object=$entrepot;
+		include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stockcorrection.tpl.php';
+		print '<br>';
+	}
+
+	/*
+	 * Transfer of units
+	 */
+	if ($action == "transfert")
+	{
+		if ($id) $object=$entrepot;
+		include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stocktransfer.tpl.php';
+		print '<br>';
+	}
+
     /*
      * Correct stock
      */
+	/*
     if ($action == "correction")
     {
         print_titre($langs->trans("StockCorrection"));
@@ -300,7 +364,7 @@ if ($resql)
         print '<input type="hidden" name="action" value="correct_stock">';
         print '<table class="border" width="100%">';
 
-        // Warehouse
+        // Product
         print '<tr>';
         print '<td width="20%">'.$langs->trans("Product").'</td>';
         print '<td width="20%">';
@@ -333,10 +397,6 @@ if ($resql)
 		print '</form>';
     }
 
-    /*
-     * Transfer of units
-     */
-    /*
     if ($action == "transfert")
     {
         print_titre($langs->trans("Transfer"));
diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php
index 50b43c4cab6..2a4acf54ff7 100644
--- a/htdocs/product/stock/product.php
+++ b/htdocs/product/stock/product.php
@@ -124,7 +124,7 @@ if ($action == "correct_stock" && ! $cancel)
 
 	if (! $error)
 	{
-		$priceunit=price2num(GETPOST("price"));
+		$priceunit=price2num(GETPOST("unitprice"));
 		if (is_numeric(GETPOST("nbpiece")) && $id)
 		{
 			if (empty($product)) {
@@ -598,83 +598,8 @@ if ($id > 0 || $ref)
 	 */
 	if ($action == "correction")
 	{
-		print '<script type="text/javascript" language="javascript">
-		jQuery(document).ready(function() {
-			function init_price()
-			{
-				if (jQuery("#mouvement").val() == \'0\') jQuery("#unitprice").removeAttr(\'disabled\');
-				else jQuery("#unitprice").attr(\'disabled\',\'disabled\');
-			}
-			init_price();
-			jQuery("#mouvement").change(function() {
-				init_price();
-			});
-		});
-		</script>';
-
-		print_titre($langs->trans("StockCorrection"));
-		print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$product->id.'" method="post">'."\n";
-		print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-		print '<input type="hidden" name="action" value="correct_stock">';
-		print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
-		print '<table class="border" width="100%">';
-
-		// Warehouse
-		print '<tr>';
-		print '<td width="20%" class="fieldrequired" colspan="2">'.$langs->trans("Warehouse").'</td>';
-		print '<td width="20%">';
-		print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot','int'):'ifone')),'id_entrepot','',1);
-		print '</td>';
-		print '<td width="20%">';
-		print '<select name="mouvement" id="mouvement" class="flat">';
-		print '<option value="0">'.$langs->trans("Add").'</option>';
-		print '<option value="1">'.$langs->trans("Delete").'</option>';
-		print '</select></td>';
-		print '<td width="20%" class="fieldrequired">'.$langs->trans("NumberOfUnit").'</td><td width="20%"><input class="flat" name="nbpiece" id="nbpiece" size="10" value="'.GETPOST("nbpiece").'"></td>';
-		print '</tr>';
-
-		// Purchase price
-		print '<tr>';
-		print '<td width="20%" colspan="2">'.$langs->trans("UnitPurchaseValue").'</td>';
-		print '<td colspan="4"><input class="flat" name="price" id="unitprice" size="10" value="'.GETPOST("unitprice").'"></td>';
-		print '</tr>';
-
-		// Eat-by date
-		if ((! empty($conf->productbatch->enabled)) && $product->hasbatch())
-		{
-			print '<tr>';
-			print '<td colspan="2">'.$langs->trans("batch_number").'</td><td colspan="4">';
-			print '<input type="text" name="batch_number" size="40" value="'.GETPOST("batch_number").'">';
-			print '</td>';
-			print '</tr><tr>';
-			print '<td colspan="2">'.$langs->trans("l_eatby").'</td><td>';
-			$form->select_date('','eatby','','',1,"");
-			print '</td>';
-			print '<td></td>';
-			print '<td>'.$langs->trans("l_sellby").'</td><td>';
-			$form->select_date('','sellby','','',1,"");
-			print '</td>';
-			print '</tr>';
-		}
-
-		// Label of mouvement of id of inventory
-		$valformovementlabel=(GETPOST("label")?GETPOST("label"):$langs->trans("MovementCorrectStock", $product->ref));
-		print '<tr>';
-		print '<td width="20%" colspan="2">'.$langs->trans("MovementLabel").'</td>';
-		print '<td colspan="2">';
-		print '<input type="text" name="label" size="40" value="'.$valformovementlabel.'">';
-		print '</td>';
-		print '<td width="20%">'.$langs->trans("InventoryCode").'</td><td width="20%"><input class="flat" name="inventorycode" id="inventorycode" size="14" value="'.GETPOST("inventorycode").'"></td>';
-		print '</tr>';
-
-		print '</table>';
-
-		print '<div class="center">';
-		print '<input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans('Save')).'">';
-		print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
-		print '<input type="submit" class="button" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
-		print '</div>';
-		print '</form>';
+		include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stockcorrection.tpl.php';
+		print '<br>';
 	}
 
 	/*
@@ -682,89 +607,8 @@ if ($id > 0 || $ref)
 	 */
 	if ($action == "transfert")
 	{
-	    $pdluoid=GETPOST('pdluoid','int');
-
-	    $pdluo = new Productbatch($db);
-
-	    if ($pdluoid > 0)
-	    {
-	        $result=$pdluo->fetch($pdluoid);
-
-	        if ($result > 0)
-	        {
-	            $pdluoid=$pdluo->id;
-	        }
-	        else
-	        {
-	            dol_print_error($db);
-	        }
-	    }
-
-		print_titre($langs->trans("StockTransfer"));
-		print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$product->id.'" method="post">'."\n";
-		print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-		print '<input type="hidden" name="action" value="transfert_stock">';
-		print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
-		if ($pdluoid)
-		{
-		    print '<input type="hidden" name="pdluoid" value="'.$pdluoid.'">';
-		}
-		print '<table class="border" width="100%">';
-
-		print '<tr>';
-		print '<td width="15%" class="fieldrequired">'.$langs->trans("WarehouseSource").'</td><td width="15%">';
-		if ($pdluoid > 0)
-		{
-		    print $formproduct->selectWarehouses($pdluo->warehouseid,'id_entrepot_source','',1,1);
-		}
-		else
-		{
-            print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot_source')?GETPOST('id_entrepot_source','int'):'ifone')),'id_entrepot_source','',1);
-		}
-		print '</td>';
-		print '<td width="15%" class="fieldrequired">'.$langs->trans("WarehouseTarget").'</td><td width="15%">';
-		print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'),'id_entrepot_destination','',1);
-		print '</td>';
-		print '<td width="15%" class="fieldrequired">'.$langs->trans("NumberOfUnit").'</td><td width="15%"><input type="text" class="flat" name="nbpiece" size="10" value="'.dol_escape_htmltag(GETPOST("nbpiece")).'"></td>';
-		print '</tr>';
-
-		// Eat-by date
-		if ((! empty($conf->productbatch->enabled)) && $product->hasbatch())
-		{
-			print '<tr>';
-			print '<td>'.$langs->trans("batch_number").'</td><td colspan="5">';
-			print '<input type="text" name="batch_number" size="40"'.($pdluoid > 0 ? ' disabled="true"':'').' value="'.(GETPOST('batch_number')?GETPOST('batch_number'):$pdluo->batch).'">';			// If form was opened for a specific pdluoid, field is disabled
-			print '</td>';
-			print '</tr><tr>';
-			print '<td>'.$langs->trans("l_eatby").'</td><td>';
-			print $form->select_date(($d_eatby?$d_eatby:$pdluo->eatby),'eatby','','',1,"", 1, 0, 1, ($pdluoid > 0 ? 1 : 0));		// If form was opened for a specific pdluoid, field is disabled
-			print '</td>';
-			print '<td>'.$langs->trans("l_sellby").'</td><td>';
-			print $form->select_date(($d_sellby?$d_sellby:$pdluo->sellby),'sellby','','',1,"", 1, 0, 1, ($pdluoid > 0 ? 1 : 0));		// If form was opened for a specific pdluoid, field is disabled
-			print '</td>';
-			print '<td colspan="2"></td>';
-			print '</tr>';
-		}
-
-		// Label
-		$valformovementlabel=(GETPOST("label")?GETPOST("label"):$langs->trans("MovementTransferStock", $product->ref));
-		print '<tr>';
-		print '<td width="15%">'.$langs->trans("MovementLabel").'</td>';
-		print '<td colspan="3">';
-		print '<input type="text" name="label" size="60" value="'.dol_escape_htmltag($valformovementlabel).'">';
-		print '</td>';
-		print '<td width="20%">'.$langs->trans("InventoryCode").'</td><td width="20%"><input class="flat" name="inventorycode" id="inventorycode" size="14" value="'.GETPOST("inventorycode").'"></td>';
-		print '</tr>';
-
-		print '</table>';
-
-		print '<div class="center">';
-		print '<input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans('Save')).'">';
-		print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
-		print '<input type="submit" class="button" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
-		print '</div>';
-
-		print '</form>';
+		include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stocktransfer.tpl.php';
+		print '<br>';
 	}
 
 	/*
diff --git a/htdocs/product/stock/tpl/stockcorrection.tpl.php b/htdocs/product/stock/tpl/stockcorrection.tpl.php
new file mode 100644
index 00000000000..8f656045ee3
--- /dev/null
+++ b/htdocs/product/stock/tpl/stockcorrection.tpl.php
@@ -0,0 +1,119 @@
+<?php
+/* Copyright (C) 2010-2015 Laurent Destailleur <eldy@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $object must be defined
+ * $product can be defined
+ */
+?>
+
+<!-- BEGIN PHP TEMPLATE STOCKCORRECTION.TPL.PHP -->
+<?php
+$langs->load("productbatch");
+
+		if (empty($id)) $id = $object->id;
+
+		print '<script type="text/javascript" language="javascript">
+		jQuery(document).ready(function() {
+			function init_price()
+			{
+				if (jQuery("#mouvement").val() == \'0\') jQuery("#unitprice").removeAttr(\'disabled\');
+				else jQuery("#unitprice").attr(\'disabled\',\'disabled\');
+			}
+			init_price();
+			jQuery("#mouvement").change(function() {
+				init_price();
+			});
+		});
+		</script>';
+
+		print_titre($langs->trans("StockCorrection"));
+		print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$id.'" method="post">'."\n";
+		print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+		print '<input type="hidden" name="action" value="correct_stock">';
+		print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
+		print '<table class="border" width="100%">';
+
+		// Warehouse or product
+		print '<tr>';
+		if ($object->element == 'product')
+		{
+			print '<td width="20%" class="fieldrequired" colspan="2">'.$langs->trans("Warehouse").'</td>';
+			print '<td width="20%">';
+			print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot')?GETPOST('id_entrepot','int'):'ifone')),'id_entrepot','',1);
+			print '</td>';
+		}
+		if ($object->element == 'stock')
+		{
+			print '<td width="20%" class="fieldrequired" colspan="2">'.$langs->trans("Product").'</td>';
+	        print '<td width="20%">';
+	        print $form->select_produits(GETPOST('product_id'),'product_id',(empty($conf->global->STOCK_SUPPORTS_SERVICES)?'0':''));
+	        print '</td>';
+		}
+		print '<td width="20%">';
+		print '<select name="mouvement" id="mouvement" class="flat">';
+		print '<option value="0">'.$langs->trans("Add").'</option>';
+		print '<option value="1">'.$langs->trans("Delete").'</option>';
+		print '</select></td>';
+		print '<td width="20%" class="fieldrequired">'.$langs->trans("NumberOfUnit").'</td><td width="20%"><input class="flat" name="nbpiece" id="nbpiece" size="10" value="'.GETPOST("nbpiece").'"></td>';
+		print '</tr>';
+
+		// Purchase price
+		print '<tr>';
+		print '<td width="20%" colspan="2">'.$langs->trans("UnitPurchaseValue").'</td>';
+		print '<td colspan="4"><input class="flat" name="unitprice" id="unitprice" size="10" value="'.GETPOST("unitprice").'"></td>';
+		print '</tr>';
+
+		// Eat-by date
+		if ((! empty($conf->productbatch->enabled)) && is_object($product) && $product->hasbatch())
+		{
+			print '<tr>';
+			print '<td colspan="2">'.$langs->trans("batch_number").'</td><td colspan="4">';
+			print '<input type="text" name="batch_number" size="40" value="'.GETPOST("batch_number").'">';
+			print '</td>';
+			print '</tr><tr>';
+			print '<td colspan="2">'.$langs->trans("l_eatby").'</td><td>';
+			$eatbyselected=dol_mktime(0, 0, 0, GETPOST('eatbymonth'), GETPOST('eatbyday'), GETPOST('eatbyyear'));
+			$form->select_date($eatbyselected,'eatby','','',1,"");
+			print '</td>';
+			print '<td></td>';
+			print '<td>'.$langs->trans("l_sellby").'</td><td>';
+			$sellbyselected=dol_mktime(0, 0, 0, GETPOST('sellbymonth'), GETPOST('sellbyday'), GETPOST('sellbyyear'));
+			$form->select_date($sellbyselected,'sellby','','',1,"");
+			print '</td>';
+			print '</tr>';
+		}
+
+		// Label of mouvement of id of inventory
+		$valformovementlabel=((GETPOST("label") && (GETPOST('label') != $langs->trans("MovementCorrectStock",''))) ? GETPOST("label") : $langs->trans("MovementCorrectStock", $product->ref));
+		print '<tr>';
+		print '<td width="20%" colspan="2">'.$langs->trans("MovementLabel").'</td>';
+		print '<td colspan="2">';
+		print '<input type="text" name="label" size="60" value="'.$valformovementlabel.'">';
+		print '</td>';
+		print '<td width="20%">'.$langs->trans("InventoryCode").'</td><td width="20%"><input class="flat" name="inventorycode" id="inventorycode" size="14" value="'.GETPOST("inventorycode").'"></td>';
+		print '</tr>';
+
+		print '</table>';
+
+		print '<div class="center">';
+		print '<input type="submit" class="button" name="save" value="'.dol_escape_htmltag($langs->trans('Save')).'">';
+		print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
+		print '<input type="submit" class="button" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
+		print '</div>';
+		print '</form>';
+
+?>
+<!-- END PHP STOCKCORRECTION.TPL.PHP -->
\ No newline at end of file
diff --git a/htdocs/product/stock/tpl/stocktransfer.tpl.php b/htdocs/product/stock/tpl/stocktransfer.tpl.php
new file mode 100644
index 00000000000..6325939a01e
--- /dev/null
+++ b/htdocs/product/stock/tpl/stocktransfer.tpl.php
@@ -0,0 +1,107 @@
+<?php
+/* Copyright (C) 2010-2015 Laurent Destailleur <eldy@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * $product must be defined
+ * $backtopage
+ */
+?>
+
+<!-- BEGIN PHP TEMPLATE STOCKCORRECTION.TPL.PHP -->
+<?php
+		$pdluoid=GETPOST('pdluoid','int');
+
+	    $pdluo = new Productbatch($db);
+
+	    if ($pdluoid > 0)
+	    {
+	        $result=$pdluo->fetch($pdluoid);
+	        if ($result > 0)
+	        {
+	            $pdluoid=$pdluo->id;
+	        }
+	        else
+	        {
+	            dol_print_error($db,$pdluo->error,$pdluo->errors);
+	        }
+	    }
+
+		print_titre($langs->trans("StockTransfer"));
+		print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$product->id.'" method="post">'."\n";
+		print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+		print '<input type="hidden" name="action" value="transfert_stock">';
+		print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
+		if ($pdluoid)
+		{
+		    print '<input type="hidden" name="pdluoid" value="'.$pdluoid.'">';
+		}
+		print '<table class="border" width="100%">';
+
+		print '<tr>';
+		print '<td width="15%" class="fieldrequired">'.$langs->trans("WarehouseSource").'</td><td width="15%">';
+		if ($pdluoid > 0)
+		{
+		    print $formproduct->selectWarehouses($pdluo->warehouseid,'id_entrepot_source','',1,1);
+		}
+		else
+		{
+            print $formproduct->selectWarehouses((GETPOST("dwid")?GETPOST("dwid",'int'):(GETPOST('id_entrepot_source')?GETPOST('id_entrepot_source','int'):'ifone')),'id_entrepot_source','',1);
+		}
+		print '</td>';
+		print '<td width="15%" class="fieldrequired">'.$langs->trans("WarehouseTarget").'</td><td width="15%">';
+		print $formproduct->selectWarehouses(GETPOST('id_entrepot_destination'),'id_entrepot_destination','',1);
+		print '</td>';
+		print '<td width="15%" class="fieldrequired">'.$langs->trans("NumberOfUnit").'</td><td width="15%"><input type="text" class="flat" name="nbpiece" size="10" value="'.dol_escape_htmltag(GETPOST("nbpiece")).'"></td>';
+		print '</tr>';
+
+		// Eat-by date
+		if ((! empty($conf->productbatch->enabled)) && $product->hasbatch())
+		{
+			print '<tr>';
+			print '<td>'.$langs->trans("batch_number").'</td><td colspan="5">';
+			print '<input type="text" name="batch_number" size="40"'.($pdluoid > 0 ? ' disabled="true"':'').' value="'.(GETPOST('batch_number')?GETPOST('batch_number'):$pdluo->batch).'">';			// If form was opened for a specific pdluoid, field is disabled
+			print '</td>';
+			print '</tr><tr>';
+			print '<td>'.$langs->trans("l_eatby").'</td><td>';
+			print $form->select_date(($d_eatby?$d_eatby:$pdluo->eatby),'eatby','','',1,"", 1, 0, 1, ($pdluoid > 0 ? 1 : 0));		// If form was opened for a specific pdluoid, field is disabled
+			print '</td>';
+			print '<td>'.$langs->trans("l_sellby").'</td><td>';
+			print $form->select_date(($d_sellby?$d_sellby:$pdluo->sellby),'sellby','','',1,"", 1, 0, 1, ($pdluoid > 0 ? 1 : 0));		// If form was opened for a specific pdluoid, field is disabled
+			print '</td>';
+			print '<td colspan="2"></td>';
+			print '</tr>';
+		}
+
+		// Label
+		$valformovementlabel=(GETPOST("label")?GETPOST("label"):$langs->trans("MovementTransferStock", $product->ref));
+		print '<tr>';
+		print '<td width="15%">'.$langs->trans("MovementLabel").'</td>';
+		print '<td colspan="3">';
+		print '<input type="text" name="label" size="60" value="'.dol_escape_htmltag($valformovementlabel).'">';
+		print '</td>';
+		print '<td width="20%">'.$langs->trans("InventoryCode").'</td><td width="20%"><input class="flat" name="inventorycode" id="inventorycode" size="14" value="'.GETPOST("inventorycode").'"></td>';
+		print '</tr>';
+
+		print '</table>';
+
+		print '<div class="center">';
+		print '<input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans('Save')).'">';
+		print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
+		print '<input type="submit" class="button" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
+		print '</div>';
+
+		print '</form>';
+?>
+<!-- END PHP STOCKCORRECTION.TPL.PHP -->
\ No newline at end of file
diff --git a/htdocs/societe/soc.php b/htdocs/societe/soc.php
index 7ce537bd149..ab52249166a 100644
--- a/htdocs/societe/soc.php
+++ b/htdocs/societe/soc.php
@@ -95,8 +95,8 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e
 
 if (empty($reshook))
 {
-	if ($action == 'confirm_merge' && $confirm == 'yes') {
-
+	if ($action == 'confirm_merge' && $confirm == 'yes')
+	{
 		$errors = 0;
 		$soc_origin_id = GETPOST('soc_origin', 'int');
 		$soc_origin = new Societe($db);
@@ -2291,7 +2291,11 @@ else
 			$formmail->fromid   = $user->id;
 			$formmail->fromname = $user->getFullName($langs);
 			$formmail->frommail = $user->email;
-			if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID))
+			if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 1))	// If bit 1 is set
+			{
+				$formmail->trackid='thi'.$object->id;
+			}
+			if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 2))	// If bit 2 is set
 			{
 				include DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
 				$formmail->frommail=dolAddEmailTrackId($formmail->frommail, 'thi'.$object->id);
-- 
GitLab