diff --git a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql
index 9bd984bba1b09e9e54ce8cb98828d05da834dca2..e81027fd22f8d588668ae7750fd9b8103bcfc901 100644
--- a/htdocs/install/mysql/migration/4.0.0-5.0.0.sql
+++ b/htdocs/install/mysql/migration/4.0.0-5.0.0.sql
@@ -149,4 +149,7 @@ ALTER TABLE llx_commande_fournisseurdet ADD COLUMN vat_src_code varchar(10) DEFA
 ALTER TABLE llx_propaldet ADD COLUMN vat_src_code varchar(10) DEFAULT '' AFTER tva_tx;
 ALTER TABLE llx_supplier_proposaldet ADD COLUMN vat_src_code varchar(10) DEFAULT '' AFTER tva_tx;
 
-  
+ALTER TABLE llx_c_payment_term change fdm type_cdr tinyint;
+
+ALTER TABLE llx_entrepot ADD COLUMN fk_parent integer DEFAULT 0;
+
diff --git a/htdocs/install/mysql/tables/llx_entrepot.sql b/htdocs/install/mysql/tables/llx_entrepot.sql
index a8898a7ec92b414cb23f28fa4ecad6ec8688de22..d93eb6e157532d9551233f075dd4577127aec2e4 100644
--- a/htdocs/install/mysql/tables/llx_entrepot.sql
+++ b/htdocs/install/mysql/tables/llx_entrepot.sql
@@ -34,5 +34,6 @@ create table llx_entrepot
   fk_pays         integer DEFAULT 0,
   statut          tinyint DEFAULT 1,			-- 1 open, 0 close
   fk_user_author  integer,
-  import_key	  varchar(14)
+  import_key	  varchar(14),
+  fk_parent       integer DEFAULT 0
 )ENGINE=innodb;
diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang
index 2c8d19a50c3e6a2566c8fffbb3da2fffe01afdc4..a3851b893393eaefb44a1fd7f732cabf928b6b51 100644
--- a/htdocs/langs/en_US/main.lang
+++ b/htdocs/langs/en_US/main.lang
@@ -62,6 +62,7 @@ ErrorCantLoadUserFromDolibarrDatabase=Failed to find user <b>%s</b> in Dolibarr
 ErrorNoVATRateDefinedForSellerCountry=Error, no vat rates defined for country '%s'.
 ErrorNoSocialContributionForSellerCountry=Error, no social/fiscal taxes type defined for country '%s'.
 ErrorFailedToSaveFile=Error, failed to save file.
+ErrorCannotAddThisParentWarehouse=You are trying to add a parent warehouse which is already a child of current one
 NotAuthorized=You are not authorized to do that.
 SetDate=Set date
 SelectDate=Select a date
diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang
index 413e6c8008871a50726f77d12eb6fa547de5b3da..d5fa618b1e0ec05d75f8932f61d85bf3bc73992e 100644
--- a/htdocs/langs/en_US/stocks.lang
+++ b/htdocs/langs/en_US/stocks.lang
@@ -2,6 +2,7 @@
 WarehouseCard=Warehouse card
 Warehouse=Warehouse
 Warehouses=Warehouses
+ParentWarehouse=Parent warehouse
 NewWarehouse=New warehouse / Stock area
 WarehouseEdit=Modify warehouse
 MenuNewWarehouse=New warehouse
diff --git a/htdocs/product/class/html.formproduct.class.php b/htdocs/product/class/html.formproduct.class.php
index cedf40678d24582116adbb1290d8c69e38094b0c..d1fe225ba0e4b1eaac0a6ec4264f9188ac8494d7 100644
--- a/htdocs/product/class/html.formproduct.class.php
+++ b/htdocs/product/class/html.formproduct.class.php
@@ -56,15 +56,18 @@ class FormProduct
 	 * @param	string	$batch			    Add quantity of batch stock in label for product with batch name batch, batch name precedes batch_id. Nothing if ''.
 	 * @param	int		$status		      	additional filter on status other then 1
 	 * @param	boolean	$sumStock		    sum total stock of a warehouse, default true
+	 * @param	array	$exclude		    warehouses ids to exclude
 	 * @return  int  		    		    Nb of loaded lines, 0 if already loaded, <0 if KO
 	 */
-	function loadWarehouses($fk_product=0, $batch = '', $status=null, $sumStock = true)
+	function loadWarehouses($fk_product=0, $batch = '', $status=null, $sumStock = true, $exclude='')
 	{
 		global $conf, $langs;
 
 		if (empty($fk_product) && count($this->cache_warehouses)) return 0;    // Cache already loaded and we do not want a list with information specific to a product
-
-		$sql = "SELECT e.rowid, e.label, e.description";
+		
+		if (is_array($exclude))	$excludeGroups = implode("','",$exclude);
+		
+		$sql = "SELECT e.rowid, e.label, e.description, e.fk_parent";
 		if (!empty($fk_product)) 
 		{
 			if (!empty($batch)) 
@@ -100,6 +103,8 @@ class FormProduct
 			$sql.= " AND e.statut = 1";
 		}
 		
+		if(!empty($exclude)) $sql.= ' AND e.rowid NOT IN('.implode(',', $exclude).')';
+		
 		if ($sumStock && empty($fk_product)) $sql.= " GROUP BY e.rowid, e.label, e.description";
 		$sql.= " ORDER BY e.label";
 
@@ -115,10 +120,17 @@ class FormProduct
 				if ($sumStock) $obj->stock = price2num($obj->stock,5);
 				$this->cache_warehouses[$obj->rowid]['id'] =$obj->rowid;
 				$this->cache_warehouses[$obj->rowid]['label']=$obj->label;
+				$this->cache_warehouses[$obj->rowid]['parent_id']=$obj->fk_parent;
 				$this->cache_warehouses[$obj->rowid]['description'] = $obj->description;
 				$this->cache_warehouses[$obj->rowid]['stock'] = $obj->stock;
 				$i++;
 			}
+			
+			// Full label init
+			foreach($this->cache_warehouses as $obj_rowid=>$tab) {
+				$this->cache_warehouses[$obj_rowid]['full_label'] = $this->get_parent_path($tab);
+			}
+
 			return $num;
 		}
 		else
@@ -127,6 +139,29 @@ class FormProduct
 			return -1;
 		}
 	}
+	
+	/**
+	 * Return full path to current warehouse in $tab (recursive function)
+	 * 
+	 * @param	array	$tab			warehouse data in $this->cache_warehouses line
+	 * @param	String	$final_label	full label with all parents, separated by ' >> ' (completed on each call)
+	 * @return	String					full label with all parents, separated by ' >> '
+	 */
+	private function get_parent_path($tab, $final_label='') {
+		
+		if(empty($final_label)) $final_label = $tab['label'];
+		
+		if(empty($tab['parent_id'])) return $final_label;
+		else {
+			if(!empty($this->cache_warehouses[$tab['parent_id']])) {
+				$final_label = $this->cache_warehouses[$tab['parent_id']]['label'].' >> '.$final_label;
+				return $this->get_parent_path($this->cache_warehouses[$tab['parent_id']], $final_label);
+			}
+		}
+		
+		return $final_label;
+		
+	}
 
 	/**
 	 *  Return list of warehouses
@@ -142,9 +177,10 @@ class FormProduct
 	 *  @param	int		$forcecombo		force combo iso ajax select2
 	 *  @param	array	$events			events to add to select2
 	 *  @param  string  $morecss        Add more css classes
+	 *  @param	array	$exclude		warehouses ids to exclude
 	 * 	@return	string					HTML select
 	 */
-	function selectWarehouses($selected='',$htmlname='idwarehouse',$filtertype='',$empty=0,$disabled=0,$fk_product=0,$empty_label='', $showstock=0, $forcecombo=0, $events=array(), $morecss='minwidth200')
+	function selectWarehouses($selected='',$htmlname='idwarehouse',$filtertype='',$empty=0,$disabled=0,$fk_product=0,$empty_label='', $showstock=0, $forcecombo=0, $events=array(), $morecss='minwidth200', $exclude='')
 	{
 		global $conf,$langs,$user;
 
@@ -152,7 +188,7 @@ class FormProduct
 		
 		$out='';
 		
-		$this->loadWarehouses($fk_product, '', + $filtertype); // filter on numeric status
+		$this->loadWarehouses($fk_product, '', + $filtertype, true, $exclude); // filter on numeric status
 		$nbofwarehouses=count($this->cache_warehouses);
 
 		if ($conf->use_javascript_ajax && ! $forcecombo)
@@ -170,7 +206,7 @@ class FormProduct
 			$out.='<option value="'.$id.'"';
 			if ($selected == $id || ($selected == 'ifone' && $nbofwarehouses == 1)) $out.=' selected';
 			$out.='>';
-			$out.=$arraytypes['label'];
+			$out.=$arraytypes['full_label'];
 			if (($fk_product || ($showstock > 0)) && ($arraytypes['stock'] != 0 || ($showstock > 0))) $out.=' ('.$langs->trans("Stock").':'.$arraytypes['stock'].')';
 			$out.='</option>';
 		}
diff --git a/htdocs/product/stock/card.php b/htdocs/product/stock/card.php
index 60f7938de06e0fd7d0a0f7302c76ca967d4a0786..5adff357db1c7c85e53fe692992dc63cbb22acec 100644
--- a/htdocs/product/stock/card.php
+++ b/htdocs/product/stock/card.php
@@ -31,10 +31,12 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/stock.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
+require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
 
 $langs->load("products");
 $langs->load("stocks");
 $langs->load("companies");
+$langs->load("categories");
 
 $action=GETPOST('action');
 $cancel=GETPOST('cancel');
@@ -64,6 +66,7 @@ $object = new Entrepot($db);
 if ($action == 'add' && $user->rights->stock->creer)
 {
 	$object->ref         = GETPOST("ref");
+	$object->fk_parent   = GETPOST("fk_parent");
 	$object->libelle     = GETPOST("libelle");
 	$object->description = GETPOST("desc");
 	$object->statut      = GETPOST("statut");
@@ -128,6 +131,7 @@ if ($action == 'update' && $cancel <> $langs->trans("Cancel"))
 	if ($object->fetch($id))
 	{
 		$object->libelle     = GETPOST("libelle");
+		$object->fk_parent   = GETPOST("fk_parent");
 		$object->description = GETPOST("desc");
 		$object->statut      = GETPOST("statut");
 		$object->lieu        = GETPOST("lieu");
@@ -166,6 +170,7 @@ if ($cancel == $langs->trans("Cancel"))
 
 $productstatic=new Product($db);
 $form=new Form($db);
+$formproduct=new FormProduct($db);
 $formcompany=new FormCompany($db);
 
 $help_url='EN:Module_Stocks_En|FR:Module_Stock|ES:M&oacute;dulo_Stocks';
@@ -189,6 +194,11 @@ if ($action == 'create')
 	print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Ref").'</td><td colspan="3"><input name="libelle" size="20" value=""></td></tr>';
 
 	print '<tr><td >'.$langs->trans("LocationSummary").'</td><td colspan="3"><input name="lieu" size="40" value="'.(!empty($object->lieu)?$object->lieu:'').'"></td></tr>';
+		
+	// Parent entrepot
+	print '<tr><td>'.$langs->trans("AddIn").'</td><td>';
+	print $formproduct->selectWarehouses('', 'fk_parent', '', 1);
+	print '</td></tr>';
 
 	// Description
 	print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td colspan="3">';
@@ -346,6 +356,16 @@ else
 
 			//print '<tr><td>'.$langs->trans("LocationSummary").'</td><td colspan="3">'.$object->lieu.'</td></tr>';
 
+			// Parent entrepot
+			$e = new Entrepot($db);
+			if(!empty($object->fk_parent) && $e->fetch($object->fk_parent) > 0) {
+				
+				print '<tr><td>'.$langs->trans("ParentWarehouse").'</td><td>';
+				print $e->getNomUrl(3);
+				print '</td></tr>';
+				
+			}
+
 			// Description
 			print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td>'.nl2br($object->description).'</td></tr>';
 
@@ -623,6 +643,11 @@ else
 			print '<tr><td width="20%" class="fieldrequired">'.$langs->trans("Ref").'</td><td colspan="3"><input name="libelle" size="20" value="'.$object->libelle.'"></td></tr>';
 
 			print '<tr><td>'.$langs->trans("LocationSummary").'</td><td colspan="3"><input name="lieu" size="40" value="'.$object->lieu.'"></td></tr>';
+		
+			// Parent entrepot
+			print '<tr><td>'.$langs->trans("AddIn").'</td><td>';
+			print $formproduct->selectWarehouses($object->fk_parent, 'fk_parent', '', 1);
+			print '</td></tr>';
 
 			// Description
 			print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td colspan="3">';
diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php
index aee38a67ccf13995657620514e6cda584a8e9e83..032a0f3a56d5467ef6a7ca54f52052fe6be50f38 100644
--- a/htdocs/product/stock/class/entrepot.class.php
+++ b/htdocs/product/stock/class/entrepot.class.php
@@ -123,8 +123,8 @@ class Entrepot extends CommonObject
 
 		$this->db->begin();
 
-		$sql = "INSERT INTO ".MAIN_DB_PREFIX."entrepot (entity, datec, fk_user_author, label)";
-		$sql .= " VALUES (".$conf->entity.",'".$this->db->idate($now)."',".$user->id.",'".$this->db->escape($this->libelle)."')";
+		$sql = "INSERT INTO ".MAIN_DB_PREFIX."entrepot (entity, datec, fk_user_author, label, fk_parent)";
+		$sql .= " VALUES (".$conf->entity.",'".$this->db->idate($now)."',".$user->id.",'".$this->db->escape($this->libelle)."', ".($this->fk_parent > 0 ? $this->fk_parent : 'NULL').")";
 
 		dol_syslog(get_class($this)."::create", LOG_DEBUG);
 		$result=$this->db->query($sql);
@@ -172,6 +172,16 @@ class Entrepot extends CommonObject
 	 */
 	function update($id, $user)
 	{
+		// Check if new parent is already a child of current warehouse
+		if(!empty($this->fk_parent)) {
+			$TChildWarehouses = array($id);
+			$TChildWarehouses = $this->get_children_warehouses($this->id, $TChildWarehouses);
+			if(in_array($this->fk_parent, $TChildWarehouses)) {
+				$this->error = 'ErrorCannotAddThisParentWarehouse';
+				return -2;
+			}
+		}
+		
 		$this->libelle=trim($this->libelle);
 		$this->description=trim($this->description);
 
@@ -184,6 +194,7 @@ class Entrepot extends CommonObject
 
 		$sql = "UPDATE ".MAIN_DB_PREFIX."entrepot ";
 		$sql .= " SET label = '" . $this->db->escape($this->libelle) ."'";
+		$sql .= ", fk_parent = '" . (($this->fk_parent > 0) ? $this->fk_parent : 'NULL') ."'";
 		$sql .= ", description = '" . $this->db->escape($this->description) ."'";
 		$sql .= ", statut = " . $this->statut;
 		$sql .= ", lieu = '" . $this->db->escape($this->lieu) ."'";
@@ -294,7 +305,7 @@ class Entrepot extends CommonObject
 	{
 		global $conf;
 
-		$sql  = "SELECT rowid, label, description, statut, lieu, address, zip, town, fk_pays as country_id";
+		$sql  = "SELECT rowid, fk_parent, label, description, statut, lieu, address, zip, town, fk_pays as country_id";
 		$sql .= " FROM ".MAIN_DB_PREFIX."entrepot";
 
 		if ($id)
@@ -317,6 +328,7 @@ class Entrepot extends CommonObject
 				$obj=$this->db->fetch_object($result);
 
 				$this->id             = $obj->rowid;
+				$this->fk_parent      = $obj->fk_parent;
 				$this->ref            = $obj->rowid;
 				$this->libelle        = $obj->label;
 				$this->description    = $obj->description;
@@ -573,7 +585,7 @@ class Entrepot extends CommonObject
         $linkend='</a>';
 
         if ($withpicto) $result.=($link.img_object($label, 'stock', 'class="classfortooltip"').$linkend.' ');
-		$result.=$link.(empty($this->label)?$this->libelle:$this->label).$linkend;
+		$result.=$link.$this->get_full_arbo().$linkend;
 		return $result;
 	}
 
@@ -604,4 +616,69 @@ class Entrepot extends CommonObject
         $this->country_id=1;
         $this->country_code='FR';
     }
+	
+	/**
+	 *	Return full path to current warehouse
+	 *
+	 * 	@param		int		$protection		Deep counter to avoid infinite loop
+	 *	@return		string	String full path to current warehouse separated by " >> " 
+	 */
+	function get_full_arbo($protection=1000) {
+		
+		 global $user,$langs,$conf;
+		 
+		 $TArbo = array($this->libelle);
+		 
+		 $id = $this->id;
+		
+		 $i=0;
+
+		 while((empty($protection) || $i < $protection)) {
+			 $sql = 'SELECT fk_parent
+			 		FROM '.MAIN_DB_PREFIX.'entrepot
+			 		WHERE rowid = '.$id;
+
+			 $resql = $this->db->query($sql);
+			 if($resql) {
+			 	$res = $this->db->fetch_object($resql);
+			 	if(empty($res->fk_parent)) break;
+				$id = $res->fk_parent;
+				$o = new Entrepot($this->db);
+				$o->fetch($id);
+				$TArbo[] = $o->libelle;
+			 } else break;
+			 
+			 $i++;
+			 
+		 }
+
+		 return implode(' >> ', array_reverse($TArbo));
+		
+	}
+	
+	/**
+	 * Return array of children warehouses ids from $id warehouse (recursive function)
+	 * 
+	 * @param	int		$id					id parent warehouse
+	 * @param	array()	$TChildWarehouses	array which will contain all children (param by reference)
+	 * @return	array()	$TChildWarehouses	array which will contain all children
+	 */
+	function get_children_warehouses($id, &$TChildWarehouses) {
+		
+		$sql = 'SELECT rowid
+				FROM '.MAIN_DB_PREFIX.'entrepot
+				WHERE fk_parent = '.$id;
+		
+		$resql = $this->db->query($sql);
+		if($resql) {
+			while($res = $this->db->fetch_object($resql)) {
+				$TChildWarehouses[] = $res->rowid;
+				$this->get_children_warehouses($res->rowid, $TChildWarehouses);
+			}
+		}
+		
+		return $TChildWarehouses;
+		
+	}
+
 }