diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php
index e0b0470c4e1b9d97b1e3575a4caff1c4d841a4bf..7375f7d699b0f9ffc05d5482ebbbbb59c3e88803 100644
--- a/htdocs/comm/propal/class/propal.class.php
+++ b/htdocs/comm/propal/class/propal.class.php
@@ -2084,8 +2084,6 @@ class Propal extends CommonObject
 	 */
 	function getLinesArray()
 	{
-		$lines = array();
-
 		$sql = 'SELECT pt.rowid, pt.description, pt.fk_product, pt.fk_remise_except,';
 		$sql.= ' pt.qty, pt.tva_tx, pt.remise_percent, pt.subprice, pt.info_bits,';
 		$sql.= ' pt.total_ht, pt.total_tva, pt.total_ttc, pt.marge_tx, pt.marque_tx, pt.pa_ht, pt.special_code,';
diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php
index ffd3c299a7638d027e65ec4f756e309230dc81d9..a9d57685d9d2903b0946181e2dad21c632b62cbe 100644
--- a/htdocs/compta/facture.php
+++ b/htdocs/compta/facture.php
@@ -362,7 +362,7 @@ if ($_GET['action'] == 'modif' && $user->rights->facture->unvalidate)
 	$resteapayer = $object->total_ttc - $totalpaye;
 
 	// On verifie si les lignes de factures ont ete exportees en compta et/ou ventilees
-	$ventilExportCompta = $fac->getVentilExportCompta();
+	$ventilExportCompta = $object->getVentilExportCompta();
 
 	// On verifie si aucun paiement n'a ete effectue
 	if ($resteapayer == $object->total_ttc	&& $object->paye == 0 && $ventilExportCompta == 0)
@@ -2179,7 +2179,7 @@ else
 				print ' ('.$langs->transnoentities("CorrectInvoice",$facusing->getNomUrl(1)).')';
 			}
 
-			$facidavoir=$fac->getListIdAvoirFromInvoice();
+			$facidavoir=$object->getListIdAvoirFromInvoice();
 			if (sizeof($facidavoir) > 0)
 			{
 				print ' ('.$langs->transnoentities("InvoiceHasAvoir");
@@ -2624,6 +2624,10 @@ else
 			/*
 			 * Inoice lines
 			 */
+			
+			print '<table class="noborder" width="100%">';
+			
+			/*
 
 			$sql = 'SELECT l.fk_product, l.product_type, l.description, l.qty, l.rowid, l.tva_tx,';
 			$sql.= ' l.fk_remise_except,';
@@ -2902,6 +2906,16 @@ else
 			{
 				dol_print_error($db);
 			}
+			
+			*/
+			
+			$result = $object->getLinesArray();
+			
+			if (!empty($object->lines))
+			{
+				$object->print_title_list();
+				$object->printLinesList();
+			}
 
 			/*
 			 * Form to add new line
@@ -2918,6 +2932,16 @@ else
 					$var=!$var;
 					$object->showAddPredefinedProductForm(1);
 				}
+				
+				// Hook of thirdparty module
+				if (! empty($object->hooks))
+				{
+					foreach($object->hooks as $module)
+					{
+						$var=!$var;
+						$module->formAddObject($object);
+					}
+				}
 			}
 
 			print "</table>\n";
@@ -3145,11 +3169,11 @@ else
 				 */
 				$object->load_object_linked($object->id,$object->element);
 
-				foreach($object->linked_object as $object => $objectid)
+				foreach($object->linked_object as $objecttype => $objectid)
 				{
-					if($conf->$object->enabled && $object != $object->element)
+					if($conf->$objecttype->enabled && $objecttype != $object->element)
 					{
-						$somethingshown=$object->showLinkedObjectBlock($object,$objectid,$somethingshown);
+						$somethingshown=$object->showLinkedObjectBlock($objecttype,$objectid,$somethingshown);
 					}
 				}
 
diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php
index eaf1cc446b5fb8b57661af59559dc95fe10a1734..86bcd77307d109b8743d6aeef47c248215928965 100644
--- a/htdocs/compta/facture/class/facture.class.php
+++ b/htdocs/compta/facture/class/facture.class.php
@@ -4,7 +4,7 @@
  * Copyright (C) 2004      Sebastien Di Cintio   <sdicintio@ressource-toi.org>
  * Copyright (C) 2004      Benoit Mortier        <benoit.mortier@opensides.be>
  * Copyright (C) 2005      Marc Barilley / Ocebo <marc@ocebo.com>
- * Copyright (C) 2005-2009 Regis Houssin         <regis@dolibarr.fr>
+ * Copyright (C) 2005-2010 Regis Houssin         <regis@dolibarr.fr>
  * Copyright (C) 2006      Andre Cianfarani      <acianfa@free.fr>
  * Copyright (C) 2007      Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
  * Copyright (C) 2010      Juanjo Menent         <jmenent@2byte.es>
@@ -101,6 +101,7 @@ class Facture extends CommonObject
 	var $products=array();
 	var $lignes=array();	// TODO deprecated
 	var $lines=array();
+	var $line;
 	//! Pour board
 	var $nbtodo;
 	var $nbtodolate;
@@ -672,6 +673,7 @@ class Facture extends CommonObject
 	{
 		$sql = 'SELECT l.rowid, l.fk_product, l.description, l.product_type, l.price, l.qty, l.tva_tx, ';
 		$sql.= ' l.localtax1_tx, l.localtax2_tx, l.remise, l.remise_percent, l.fk_remise_except, l.subprice,';
+		$sql.= ' l.rang, l.special_code,';
 		$sql.= ' l.date_start as date_start, l.date_end as date_end,';
 		$sql.= ' l.info_bits, l.total_ht, l.total_tva, l.total_localtax1, l.total_localtax2, l.total_ttc, l.fk_code_ventilation, l.fk_export_compta,';
 		$sql.= ' p.ref as product_ref, p.fk_product_type as fk_product_type, p.label as label, p.description as product_desc';
@@ -718,6 +720,8 @@ class Facture extends CommonObject
 				$line->total_ttc        = $objp->total_ttc;
 				$line->export_compta    = $objp->fk_export_compta;
 				$line->code_ventilation = $objp->fk_code_ventilation;
+				$line->rang				= $objp->rang;
+				$line->special_code		= $objp->special_code;
 
 				// Ne plus utiliser
 				$line->price            = $objp->price;
@@ -1593,7 +1597,7 @@ class Facture extends CommonObject
 	 *					par l'appelant par la methode get_default_tva(societe_vendeuse,societe_acheteuse,produit)
 	 *					et le desc doit deja avoir la bonne valeur (a l'appelant de gerer le multilangue)
 	 */
-	function addline($facid, $desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $date_start='', $date_end='', $ventil=0, $info_bits=0, $fk_remise_except='', $price_base_type='HT', $pu_ttc=0, $type=0, $rang=-1)
+	function addline($facid, $desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $date_start='', $date_end='', $ventil=0, $info_bits=0, $fk_remise_except='', $price_base_type='HT', $pu_ttc=0, $type=0, $rang=-1, $special_code=0)
 	{
 		dol_syslog("Facture::Addline facid=$facid,desc=$desc,pu_ht=$pu_ht,qty=$qty,txtva=$txtva, txlocaltax1=$txlocaltax1, txlocaltax2=$txlocaltax2, fk_product=$fk_product,remise_percent=$remise_percent,date_start=$date_start,date_end=$date_end,ventil=$ventil,info_bits=$info_bits,fk_remise_except=$fk_remise_except,price_base_type=$price_base_type,pu_ttc=$pu_ttc,type=$type", LOG_DEBUG);
 		include_once(DOL_DOCUMENT_ROOT.'/lib/price.lib.php');
@@ -1668,34 +1672,35 @@ class Facture extends CommonObject
 			}
 
 			// Insert line
-			$ligne=new FactureLigne($this->db);
-			$ligne->fk_facture=$facid;
-			$ligne->desc=$desc;
-			$ligne->qty=$qty;
-			$ligne->tva_tx=$txtva;
-			$ligne->localtax1_tx=$txlocaltax1;
-			$ligne->localtax2_tx=$txlocaltax2;
-			$ligne->fk_product=$fk_product;
-			$ligne->product_type=$product_type;
-			$ligne->remise_percent=$remise_percent;
-			$ligne->subprice=$pu_ht;
-			$ligne->date_start=$date_start;
-			$ligne->date_end=$date_end;
-			$ligne->ventil=$ventil;
-			$ligne->rang=$rangtouse;
-			$ligne->info_bits=$info_bits;
-			$ligne->fk_remise_except=$fk_remise_except;
-			$ligne->total_ht=$total_ht;
-			$ligne->total_tva=$total_tva;
-			$ligne->total_localtax1=$total_localtax1;
-			$ligne->total_localtax2=$total_localtax2;
-			$ligne->total_ttc=$total_ttc;
+			$this->line=new FactureLigne($this->db);
+			$this->line->fk_facture=$facid;
+			$this->line->desc=$desc;
+			$this->line->qty=$qty;
+			$this->line->tva_tx=$txtva;
+			$this->line->localtax1_tx=$txlocaltax1;
+			$this->line->localtax2_tx=$txlocaltax2;
+			$this->line->fk_product=$fk_product;
+			$this->line->product_type=$product_type;
+			$this->line->remise_percent=$remise_percent;
+			$this->line->subprice=$pu_ht;
+			$this->line->date_start=$date_start;
+			$this->line->date_end=$date_end;
+			$this->line->ventil=$ventil;
+			$this->line->rang=$rangtouse;
+			$this->line->info_bits=$info_bits;
+			$this->line->fk_remise_except=$fk_remise_except;
+			$this->line->total_ht=$total_ht;
+			$this->line->total_tva=$total_tva;
+			$this->line->total_localtax1=$total_localtax1;
+			$this->line->total_localtax2=$total_localtax2;
+			$this->line->total_ttc=$total_ttc;
+			$this->line->special_code=$special_code;
 
 			// \TODO Ne plus utiliser
-			$ligne->price=$price;
-			$ligne->remise=$remise;
+			$this->line->price=$price;
+			$this->line->remise=$remise;
 
-			$result=$ligne->insert();
+			$result=$this->line->insert();
 			if ($result > 0)
 			{
 				// Mise a jour informations denormalisees au niveau de la facture meme
@@ -2889,6 +2894,71 @@ class Facture extends CommonObject
 			return -1;
 		}
 	}
+	
+	/**
+	 * 	Return an array of invoice lines
+	 */
+	function getLinesArray()
+	{
+		$sql = 'SELECT l.rowid, l.description, l.fk_product, l.product_type, l.qty, l.tva_tx,';
+		$sql.= ' l.fk_remise_except,';
+		$sql.= ' l.remise_percent, l.subprice, l.info_bits, l.rang, l.special_code,';
+		$sql.= ' l.total_ht, l.total_tva, l.total_ttc,';
+		$sql.= ' l.date_start,';
+		$sql.= ' l.date_end,';
+		$sql.= ' l.product_type,';
+		$sql.= ' p.ref as product_ref, p.fk_product_type, p.label as product_label,';
+		$sql.= ' p.description as product_desc';
+		$sql.= ' FROM '.MAIN_DB_PREFIX.'facturedet as l';
+		$sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product p ON l.fk_product=p.rowid';
+		$sql.= ' WHERE l.fk_facture = '.$this->id;
+		$sql.= ' ORDER BY l.rang ASC, l.rowid';
+
+		$resql = $this->db->query($sql);
+		if ($resql)
+		{
+			$num = $this->db->num_rows($resql);
+			$i = 0;
+
+			while ($i < $num)
+			{
+				$obj = $this->db->fetch_object($resql);
+
+				$this->lines[$i]->id				= $obj->rowid;
+				$this->lines[$i]->description 		= $obj->description;
+				$this->lines[$i]->fk_product		= $obj->fk_product;
+				$this->lines[$i]->ref				= $obj->product_ref;
+				$this->lines[$i]->product_label		= $obj->product_label;
+				$this->lines[$i]->product_desc		= $obj->product_desc;
+				$this->lines[$i]->fk_product_type	= $obj->fk_product_type;
+				$this->lines[$i]->product_type		= $obj->product_type;
+				$this->lines[$i]->qty				= $obj->qty;
+				$this->lines[$i]->subprice			= $obj->subprice;
+				$this->lines[$i]->fk_remise_except 	= $obj->fk_remise_except;
+				$this->lines[$i]->remise_percent	= $obj->remise_percent;
+				$this->lines[$i]->tva_tx			= $obj->tva_tx;
+				$this->lines[$i]->info_bits			= $obj->info_bits;
+				$this->lines[$i]->total_ht			= $obj->total_ht;
+				$this->lines[$i]->total_tva			= $obj->total_tva;
+				$this->lines[$i]->total_ttc			= $obj->total_ttc;
+				$this->lines[$i]->special_code		= $obj->special_code;
+				$this->lines[$i]->rang				= $obj->rang;
+				$this->lines[$i]->date_start		= $this->db->jdate($obj->date_start);
+				$this->lines[$i]->date_end			= $this->db->jdate($obj->date_end);
+
+				$i++;
+			}
+			$this->db->free($resql);
+			
+			return 1;
+		}
+		else
+		{
+			$this->error=$this->db->error();
+			dol_syslog("Error sql=$sql, error=".$this->error,LOG_ERR);
+			return -1;
+		}
+	}
 
 }
 
@@ -2925,6 +2995,11 @@ class FactureLigne
 	var $info_bits = 0;		// Liste d'options cumulables:
 	// Bit 0:	0 si TVA normal - 1 si TVA NPR
 	// Bit 1:	0 si ligne normal - 1 si bit discount (link to line into llx_remise_except)
+	
+	var $special_code;	// Liste d'options non cumulabels:
+	// 1: frais de port
+	// 2: ecotaxe
+	// 3: ??
 
 	//! Total HT  de la ligne toute quantite et incluant la remise ligne
 	var $total_ht;
@@ -3042,6 +3117,7 @@ class FactureLigne
         if (empty($this->info_bits)) $this->info_bits=0;
         if (empty($this->subprice)) $this->subprice=0;
         if (empty($this->price))    $this->price=0;
+        if (empty($this->special_code)) $this->special_code=0;
 
         // Check parameters
         if ($this->product_type < 0) return -1;
@@ -3053,7 +3129,7 @@ class FactureLigne
 		$sql.= ' (fk_facture, description, qty, tva_tx, localtax1_tx, localtax2_tx,';
 		$sql.= ' fk_product, product_type, remise_percent, subprice, price, remise, fk_remise_except,';
 		$sql.= ' date_start, date_end, fk_code_ventilation, fk_export_compta, ';
-		$sql.= ' rang,';
+		$sql.= ' rang, special_code,';
 		$sql.= ' info_bits, total_ht, total_tva, total_localtax1, total_localtax2, total_ttc)';
 		$sql.= " VALUES (".$this->fk_facture.",";
 		$sql.= " '".addslashes($this->desc)."',";
@@ -3077,6 +3153,7 @@ class FactureLigne
 		$sql.= ' '.$this->fk_code_ventilation.',';
 		$sql.= ' '.$this->fk_export_compta.',';
 		$sql.= ' '.$this->rang.',';
+		$sql.= ' '.$this->special_code.',';
 		$sql.= " '".$this->info_bits."',";
 		$sql.= " ".price2num($this->total_ht).",";
 		$sql.= " ".price2num($this->total_tva).",";
diff --git a/htdocs/includes/modules/facture/pdf_crabe.modules.php b/htdocs/includes/modules/facture/pdf_crabe.modules.php
index ea8e71c09a54da73a4896f90846440922815d73a..c624885a64dad59e51b6fe48c1444f694a3ff6ef 100644
--- a/htdocs/includes/modules/facture/pdf_crabe.modules.php
+++ b/htdocs/includes/modules/facture/pdf_crabe.modules.php
@@ -257,29 +257,33 @@ class pdf_crabe extends ModelePDFFactures
 					// TVA
 					if (empty($conf->global->MAIN_GENERATE_DOCUMENTS_WITHOUT_VAT))
 					{
+						$vat_rate = pdf_getlinevatrate($object, $i, $outputlangs);
 						$pdf->SetXY ($this->posxtva, $curY);
-						$pdf->MultiCell($this->posxup-$this->posxtva-1, 3, vatrate($object->lines[$i]->tva_tx,1,$object->lines[$i]->info_bits), 0, 'R');
+						$pdf->MultiCell($this->posxup-$this->posxtva-1, 3, $vat_rate, 0, 'R');
 					}
 
 					// Prix unitaire HT avant remise
+					$up_excl_tax = pdf_getlineupexcltax($object, $i, $outputlangs);
 					$pdf->SetXY ($this->posxup, $curY);
-					$pdf->MultiCell($this->posxqty-$this->posxup-1, 3, price($object->lines[$i]->subprice), 0, 'R', 0);
+					$pdf->MultiCell($this->posxqty-$this->posxup-1, 3, $up_excl_tax, 0, 'R', 0);
 
 					// Quantity
+					$qty = pdf_getlineqty($object, $i, $outputlangs);
 					$pdf->SetXY ($this->posxqty, $curY);
-					$pdf->MultiCell($this->posxdiscount-$this->posxqty-1, 3, $object->lines[$i]->qty, 0, 'R');	// Enough for 6 chars
+					$pdf->MultiCell($this->posxdiscount-$this->posxqty-1, 3, $qty, 0, 'R');	// Enough for 6 chars
 
 					// Remise sur ligne
 					$pdf->SetXY ($this->posxdiscount, $curY);
 					if ($object->lines[$i]->remise_percent)
 					{
-						$pdf->MultiCell($this->postotalht-$this->posxdiscount-1, 3, dol_print_reduction($object->lines[$i]->remise_percent,$outputlangs), 0, 'R');
+						$remise_percent = pdf_getlineremisepercent($object, $i, $outputlangs);
+						$pdf->MultiCell($this->postotalht-$this->posxdiscount-1, 3, $remise_percent, 0, 'R');
 					}
 
 					// Total HT ligne
+					$total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs);
 					$pdf->SetXY ($this->postotalht, $curY);
-					$total = price($object->lines[$i]->total_ht);
-					$pdf->MultiCell(26, 3, $total, 0, 'R', 0);
+					$pdf->MultiCell(26, 3, $total_excl_tax, 0, 'R', 0);
 
 					// Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva
 					$tvaligne=$object->lines[$i]->total_tva;