diff --git a/ChangeLog b/ChangeLog
index 0b6341ffbc1cf779a2da7b55b50f9897369f6b4f..89978452254eb089ed872dc8dbc008d84ad19b46 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -21,7 +21,11 @@ For users:
 - New: Can define a default choice for choice "More action when recording
   a subscription" (foundation module).
 - New: Add link to check professional id for india.
-
+- New: [ task #731 ] Uniformize ref generation
+- New: [ task #748 ] Add a link "Dolibarr" into left menu
+- New: Script email_unpaid_invoices_to_representative accepts now a parameter test
+  and a delay.
+  
 For translators:
 - Update language files.
 
diff --git a/dev/skeletons/modMyModule.class.php b/dev/skeletons/modMyModule.class.php
index 7abeeb913b10969a41b467e7a2a2f4601738442e..2ac35dbd34019f3c22391a39c70ed413e7f20669 100644
--- a/dev/skeletons/modMyModule.class.php
+++ b/dev/skeletons/modMyModule.class.php
@@ -228,6 +228,7 @@ class modMyModule extends DolibarrModules
 		// $this->export_sql_end[$r]  =' FROM ('.MAIN_DB_PREFIX.'facture as f, '.MAIN_DB_PREFIX.'facturedet as fd, '.MAIN_DB_PREFIX.'societe as s)';
 		// $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (fd.fk_product = p.rowid)';
 		// $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture';
+		// $this->export_sql_order[$r] .=' ORDER BY s.nom';
 		// $r++;
 	}
 
diff --git a/htdocs/admin/facture.php b/htdocs/admin/facture.php
index 57193dfdb712f147aef0ffe37557db829fdff9ff..35768104e39f2562d899c4ba9eaa74b3c1362b98 100644
--- a/htdocs/admin/facture.php
+++ b/htdocs/admin/facture.php
@@ -28,11 +28,13 @@
 
 require '../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
 
 $langs->load("admin");
 $langs->load("errors");
 $langs->load('other');
+$langs->load('bills');
 
 if (! $user->admin) accessforbidden();
 
@@ -304,6 +306,8 @@ $linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToM
 print_fiche_titre($langs->trans("BillsSetup"),$linkback,'setup');
 print '<br>';
 
+$head = invoice_admin_prepare_head(null);
+dol_fiche_head($head, 'general', $langs->trans("Invoices"), 0, 'invoice');
 
 /*
  *  Numbering module
diff --git a/htdocs/admin/prelevement.php b/htdocs/admin/prelevement.php
index bbbc307e42028aeba3025c7bf920807ce915cf83..f5dfb2bc8fb00f1cf86b21cf8fc7fabcaa55fc5a 100644
--- a/htdocs/admin/prelevement.php
+++ b/htdocs/admin/prelevement.php
@@ -181,7 +181,7 @@ if (! empty($conf->global->MAIN_MODULE_NOTIFICATION))
             $var=!$var;
             if (!$obj->fk_societe)
             {
-                $username= $obj->firstname.' '.$obj->lastname;
+                $username=dolGetFirstLastname($obj->firstname,$obj->lastname);
                 $internalusers[$obj->rowid] = $username;
             }
 
@@ -254,7 +254,7 @@ if ($resql)
         $var=!$var;
 
         print "<tr ".$bc[$var].">";
-        print '<td>'.$obj->firstname." ".$obj->lastname.'</td>';
+        print '<td>'.dolGetFirstLastname($obj->firstname,$obj->lastname).'</td>';
         $label=($langs->trans("Notify_".$obj->code)!="Notify_".$obj->code?$langs->trans("Notify_".$obj->code):$obj->label);
         print '<td>'.$label.'</td>';
         print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=deletenotif&amp;notif='.$obj->rowid.'">'.img_delete().'</a></td>';
diff --git a/htdocs/admin/propal.php b/htdocs/admin/propal.php
index 04f429f50bbc32d906fb50a2a12921453a530bbb..6c18da0e2402518a7946fcfabd2cc295b53932d3 100644
--- a/htdocs/admin/propal.php
+++ b/htdocs/admin/propal.php
@@ -31,7 +31,7 @@
 require '../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
-
+require_once DOL_DOCUMENT_ROOT.'/core/lib/propal.lib.php';
 $langs->load("admin");
 $langs->load("errors");
 $langs->load('other');
@@ -214,6 +214,7 @@ else if ($action == 'setmod')
 
 $dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']);
 
+
 llxHeader('',$langs->trans("PropalSetup"));
 
 $form=new Form($db);
@@ -223,6 +224,10 @@ $form=new Form($db);
 $linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
 print_fiche_titre($langs->trans("PropalSetup"),$linkback,'setup');
 
+$head = propal_admin_prepare_head(null);
+
+dol_fiche_head($head, 'general', $langs->trans("Propales"), 0, 'propal');
+
 /*
  *  Module numerotation
  */
diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php
index 48307e19905b27739c5684571025e6a29916c070..a6199580353ef923db1d80d18ea0ed221368e0a9 100644
--- a/htdocs/comm/action/class/actioncomm.class.php
+++ b/htdocs/comm/action/class/actioncomm.class.php
@@ -948,7 +948,7 @@ class ActionComm extends CommonObject
                     $event['startdate']=$datestart;
                     $event['duration']=$duration;	// Not required with type 'journal'
                     $event['enddate']=$dateend;		// Not required with type 'journal'
-                    $event['author']=$obj->firstname.($obj->lastname?" ".$obj->lastname:"");
+                    $event['author']=dolGetFirstLastname($obj->firstname, $obj->lastname);
                     $event['priority']=$obj->priority;
                     $event['fulldayevent']=$obj->fulldayevent;
                     $event['location']=$obj->location;
diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php
index f16579051e1a31f102f522bc0b1d2971d4f55c58..0b182c7645ffb70e4c0d0740a1b2fa6c74929d1b 100644
--- a/htdocs/comm/action/index.php
+++ b/htdocs/comm/action/index.php
@@ -486,7 +486,7 @@ if ($showbirthday)
             $event->datep=dol_mktime(0,0,0,$datearray['mon'],$datearray['mday'],$year,true);    // For full day events, date are also GMT but they wont but converted during output
             $event->datef=$event->datep;
             $event->type_code='BIRTHDAY';
-            $event->libelle=$langs->trans("Birthday").' '.$obj->firstname.' '.$obj->lastname;
+            $event->libelle=$langs->trans("Birthday").' '.dolGetFirstLastname($obj->firstname,$obj->lastname);
             $event->percentage=100;
             $event->fulldayevent=true;
 
diff --git a/htdocs/comm/admin/propal_extrafields.php b/htdocs/comm/admin/propal_extrafields.php
new file mode 100755
index 0000000000000000000000000000000000000000..9993019775e7f3d3a1e8d40331d5b7ee8250000c
--- /dev/null
+++ b/htdocs/comm/admin/propal_extrafields.php
@@ -0,0 +1,159 @@
+<?php
+/* Copyright (C) 2001-2002	Rodolphe Quiedeville	<rodolphe@quiedeville.org>
+ * Copyright (C) 2003		Jean-Louis Bergamo		<jlb@j1b.org>
+ * Copyright (C) 2004-2011	Laurent Destailleur		<eldy@users.sourceforge.net>
+ * Copyright (C) 2012		Regis Houssin			<regis.houssin@capnetworks.com>
+ *
+ * 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/>.
+ */
+
+/**
+ *      \file       htdocs/societe/admin/societe_extrafields.php
+ *		\ingroup    societe
+ *		\brief      Page to setup extra fields of third party
+ */
+
+require '../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/propal.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+
+$langs->load("companies");
+$langs->load("admin");
+
+$extrafields = new ExtraFields($db);
+$form = new Form($db);
+
+// List of supported format
+$tmptype2label=getStaticMember(get_class($extrafields),'type2label');
+$type2label=array('');
+foreach ($tmptype2label as $key => $val) $type2label[$key]=$langs->trans($val);
+
+$action=GETPOST('action', 'alpha');
+$attrname=GETPOST('attrname', 'alpha');
+$elementtype='propal';
+
+if (!$user->admin) accessforbidden();
+
+
+/*
+ * Actions
+ */
+
+require DOL_DOCUMENT_ROOT.'/core/admin_extrafields.inc.php';
+
+
+
+/*
+ * View
+ */
+
+$textobject=$langs->transnoentitiesnoconv("Propales");
+
+
+llxHeader('',$langs->trans("PropalSetup"));
+
+
+$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
+print_fiche_titre($langs->trans("PropalSetup"),$linkback,'setup');
+
+
+$head = propal_admin_prepare_head(null);
+
+dol_fiche_head($head, 'attributes', $langs->trans("Propal"), 0, 'propal');
+
+
+print $langs->trans("DefineHereComplementaryAttributes",$textobject).'<br>'."\n";
+print '<br>';
+
+dol_htmloutput_errors($mesg);
+
+// Load attribute_label
+$extrafields->fetch_name_optionals_label($elementtype);
+
+print "<table summary=\"listofattributes\" class=\"noborder\" width=\"100%\">";
+
+print '<tr class="liste_titre">';
+print '<td align="center">'.$langs->trans("Position").'</td>';
+print '<td>'.$langs->trans("Label").'</td>';
+print '<td>'.$langs->trans("AttributeCode").'</td>';
+print '<td>'.$langs->trans("Type").'</td>';
+print '<td align="right">'.$langs->trans("Size").'</td>';
+print '<td align="center">'.$langs->trans("Unique").'</td>';
+print '<td align="center">'.$langs->trans("Required").'</td>';
+print '<td width="80">&nbsp;</td>';
+print "</tr>\n";
+
+$var=True;
+foreach($extrafields->attribute_type as $key => $value)
+{
+    $var=!$var;
+    print "<tr ".$bc[$var].">";
+    print "<td>".$extrafields->attribute_pos[$key]."</td>\n";
+    print "<td>".$extrafields->attribute_label[$key]."</td>\n";
+    print "<td>".$key."</td>\n";
+    print "<td>".$type2label[$extrafields->attribute_type[$key]]."</td>\n";
+    print '<td align="right">'.$extrafields->attribute_size[$key]."</td>\n";
+    print '<td align="center">'.yn($extrafields->attribute_unique[$key])."</td>\n";
+    print '<td align="center">'.yn($extrafields->attribute_required[$key])."</td>\n";
+    print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=edit&attrname='.$key.'">'.img_edit().'</a>';
+    print "&nbsp; <a href=\"".$_SERVER["PHP_SELF"]."?action=delete&attrname=$key\">".img_delete()."</a></td>\n";
+    print "</tr>";
+    //      $i++;
+}
+
+print "</table>";
+
+dol_fiche_end();
+
+
+// Buttons
+if ($action != 'create' && $action != 'edit')
+{
+    print '<div class="tabsAction">';
+    print "<a class=\"butAction\" href=\"".$_SERVER["PHP_SELF"]."?action=create\">".$langs->trans("NewAttribute")."</a>";
+    print "</div>";
+}
+
+
+/* ************************************************************************** */
+/*                                                                            */
+/* Creation d'un champ optionnel
+ /*                                                                            */
+/* ************************************************************************** */
+
+if ($action == 'create')
+{
+    print "<br>";
+    print_titre($langs->trans('NewAttribute'));
+
+    require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php';
+}
+
+/* ************************************************************************** */
+/*                                                                            */
+/* Edition d'un champ optionnel                                               */
+/*                                                                            */
+/* ************************************************************************** */
+if ($action == 'edit' && ! empty($attrname))
+{
+    print "<br>";
+    print_titre($langs->trans("FieldEdition", $attrname));
+
+    require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php';
+}
+
+llxFooter();
+
+$db->close();
+?>
diff --git a/htdocs/comm/mailing/fiche.php b/htdocs/comm/mailing/fiche.php
index ef2655ad80cdf9c1f133630c6c8105c0f746b327..4b886f2d24f3241e59542d4f733158822d981664 100644
--- a/htdocs/comm/mailing/fiche.php
+++ b/htdocs/comm/mailing/fiche.php
@@ -209,7 +209,7 @@ if ($action == 'sendallconfirmed' && $confirm == 'yes')
 					$obj = $db->fetch_object($resql);
 
 					// sendto en RFC2822
-					$sendto = str_replace(',',' ',$obj->firstname." ".$obj->lastname)." <".$obj->email.">";
+					$sendto = str_replace(',',' ',dolGetFirstLastname($obj->firstname, $obj->lastname))." <".$obj->email.">";
 
 					// Make substitutions on topic and body. From (AA=YY;BB=CC;...) we keep YY, CC, ...
 					$other=explode(';',$obj->other);
diff --git a/htdocs/comm/propal.php b/htdocs/comm/propal.php
index 9b75519236e9c8ea1be614d0dd53da1e9efad0a5..e17940379bf9e045d358afd69a0a1d3841ddac97 100644
--- a/htdocs/comm/propal.php
+++ b/htdocs/comm/propal.php
@@ -38,6 +38,7 @@ require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/modules/propale/modules_propale.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/propal.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
 if (! empty($conf->projet->enabled))
 {
 	require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
@@ -78,6 +79,7 @@ if (! empty($user->societe_id))	$socid=$user->societe_id;
 $result = restrictedArea($user, 'propal', $id);
 
 $object = new Propal($db);
+$extrafields = new ExtraFields($db);
 
 // Load object
 if ($id > 0 || ! empty($ref))
@@ -336,6 +338,15 @@ else if ($action == 'add' && $user->rights->propal->creer)
     			}
     		}
 
+    		// Get extra fields
+    		foreach($_POST as $key => $value)
+    		{
+    			if (preg_match("/^options_/",$key))
+    			{
+    				$object->array_options[$key]=GETPOST($key);
+    			}
+    		}
+    		
     		$id = $object->create($user);
     	}
 
@@ -913,7 +924,7 @@ else if ($action == 'updateligne' && $user->rights->propal->creer && GETPOST('sa
 			GETPOST('fk_parent_line'),
 			0,
 			$fournprice,
-			$buying_price,
+			$buyingprice,
 			$label,
 			$type
 		);
@@ -1094,6 +1105,35 @@ else if ($action == 'down' && $user->rights->propal->creer)
 	header('Location: '.$_SERVER["PHP_SELF"].'?id='.$id.'#'.GETPOST('rowid'));
 	exit;
 }
+else if ($action == 'update_extras')
+{
+	// Get extra fields
+	foreach($_POST as $key => $value)
+	{
+		if (preg_match("/^options_/",$key))
+		{
+			$object->array_options[$key]=$_POST[$key];
+		}
+	}
+	// Actions on extra fields (by external module or standard code)
+	// FIXME le hook fait double emploi avec le trigger !!
+	$hookmanager->initHooks(array('propaldao'));
+	$parameters=array('id'=>$object->id);
+	$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$object,$action);    // Note that $action and $object may have been modified by some hooks
+	if (empty($reshook))
+	{
+		if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
+		{
+			$result=$object->insertExtraFields();
+			if ($result < 0)
+			{
+				$error++;
+			}
+		}
+	}
+	else if ($reshook < 0) $error++;
+	 
+}
 
 if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->rights->propal->creer)
 {
@@ -1168,6 +1208,9 @@ $formfile = new FormFile($db);
 $formpropal = new FormPropal($db);
 $companystatic=new Societe($db);
 
+// fetch optionals attributes and labels
+$extralabels=$extrafields->fetch_name_optionals_label('propal');
+
 $now=dol_now();
 
 // Add new proposal
@@ -1793,19 +1836,56 @@ else
 	}
 
 	// Other attributes
+	$res=$object->fetch_optionals($object->id,$extralabels);
 	$parameters=array('colspan' => ' colspan="3"');
 	$reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action);    // Note that $action and $object may have been modified by hook
 	if (empty($reshook) && ! empty($extrafields->attribute_label))
 	{
+		
+		if ($action == 'edit_extras')
+		{
+			print '<form enctype="multipart/form-data" action="'.$_SERVER["PHP_SELF"].'" method="post" name="formsoc">';
+			print '<input type="hidden" name="action" value="update_extras">';
+			print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+			print '<input type="hidden" name="id" value="'.$object->id.'">';
+		}
+		
+		
 	    foreach($extrafields->attribute_label as $key=>$label)
 	    {
 	        $value=(isset($_POST["options_".$key])?$_POST["options_".$key]:$object->array_options["options_".$key]);
 	   		print '<tr><td';
 	   		if (! empty($extrafields->attribute_required[$key])) print ' class="fieldrequired"';
 	   		print '>'.$label.'</td><td colspan="3">';
-	        print $extrafields->showInputField($key,$value);
+	   		if ($action == 'edit_extras' &&  $user->rights->propal->creer)
+	   		{
+	        	print $extrafields->showInputField($key,$value);
+	   		}
+	   		else
+	   		{ 
+	   			print $extrafields->showOutputField($key,$value);
+	   		}
+	   		
 	        print '</td></tr>'."\n";
 	    }
+	    
+	    if(count($extrafields->attribute_label) > 0) {
+	    	
+	    	if ($action == 'edit_extras' && $user->rights->propal->creer)
+	    	{
+	    		print '<tr><td></td><td>';
+	    		print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
+	    		print '</form>';
+	    		print '</td></tr>';
+	    		
+	    	}
+	    	else {
+	    		if ($object->statut == 0 && $user->rights->propal->creer)	    		
+	    		{
+	    			print '<tr><td></td><td><a href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=edit_extras">'.img_picto('','edit').' '.$langs->trans('Modify').'</a></td></tr>';
+	    		}
+	    	}
+	    }
 	}
 
 	// Amount HT
diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php
index 4b3686db5118f00aaead53922870da06423d9f1b..66f6bb3874d7a049385f017935f2bd831eb77e06 100644
--- a/htdocs/comm/propal/class/propal.class.php
+++ b/htdocs/comm/propal/class/propal.class.php
@@ -622,7 +622,7 @@ class Propal extends CommonObject
      */
     function create($user='', $notrigger=0)
     {
-        global $langs,$conf,$mysoc;
+        global $langs,$conf,$mysoc,$hookmanager;
         $error=0;
 
         $now=dol_now();
@@ -802,6 +802,24 @@ class Propal extends CommonObject
                     $resql=$this->update_price(1);
                     if ($resql)
                     {
+                    	// Actions on extra fields (by external module or standard code)
+                    	// FIXME le hook fait double emploi avec le trigger !!
+                    	$hookmanager->initHooks(array('propaldao'));
+                    	$parameters=array('socid'=>$this->id);
+                    	$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
+                    	if (empty($reshook))
+                    	{
+                    		if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
+                    		{
+                    			$result=$this->insertExtraFields();
+                    			if ($result < 0)
+                    			{
+                    				$error++;
+                    			}
+                    		}
+                    	}
+                    	else if ($reshook < 0) $error++;
+                    	
                         if (! $notrigger)
                         {
                             // Appel des triggers
@@ -1149,6 +1167,20 @@ class Propal extends CommonObject
                     return -1;
                 }
 
+                // Retreive all extrafield for propal
+                // fetch optionals attributes and labels
+                if(!class_exists('Extrafields'))
+                	require_once(DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php');
+                $extrafields=new ExtraFields($this->db);
+                $extralabels=$extrafields->fetch_name_optionals_label('propal',true);
+                //$this->fetch_optionals($this->id,$extralabels);
+                if (count($extralabels)>0) {
+                	$this->array_options = array();
+                }
+                foreach($extrafields->attribute_label as $key=>$label)
+                {
+                	$this->array_options['options_'.$key]=$label;
+                }   
                 return 1;
             }
 
@@ -1162,6 +1194,44 @@ class Propal extends CommonObject
             return -1;
         }
     }
+    
+    /**
+     *	Update value of extrafields on the proposal
+     *
+     *	@param      User	$user       Object user that modify
+     *	@param      double	$remise      Amount discount
+     *	@return     int         		<0 if ko, >0 if ok
+     */
+    function update_extrafields($user)
+    {
+    	// Actions on extra fields (by external module or standard code)
+    	// FIXME le hook fait double emploi avec le trigger !!
+    	$hookmanager->initHooks(array('propaldao'));
+    	$parameters=array('id'=>$this->id);
+    	$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
+    	if (empty($reshook))
+    	{
+    		if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
+    		{
+    			$result=$this->insertExtraFields();
+    			if ($result < 0)
+    			{
+    				$error++;
+    			}
+    		}
+    	}
+    	else if ($reshook < 0) $error++;
+    	
+		if (!$error)
+	    {
+	    	return 1;
+	    }
+	    else
+	    {
+	    	return -1;
+	    }
+    	
+    }
 
     /**
      *  Set status to validated
diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php
index 7585b71cf684f7e17142bf63d741069666d80936..17947e6e3edd8e4c7aea3b912db2236e6f416ec8 100644
--- a/htdocs/compta/facture.php
+++ b/htdocs/compta/facture.php
@@ -7,6 +7,7 @@
  * Copyright (C) 2006      Andre Cianfarani      <acianfa@free.fr>
  * Copyright (C) 2010-2013 Juanjo Menent         <jmenent@2byte.es>
  * Copyright (C) 2012      Christophe Battarel   <christophe.battarel@altairis.fr>
+ * Copyright (C) 2013      Jean-Francois FERRY   <jfefe@aternatik.fr>
  *
  * 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
@@ -38,6 +39,7 @@ require DOL_DOCUMENT_ROOT . '/core/class/html.formother.class.php';
 require DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php';
 require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
+require DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php';
 
 if (! empty($conf->commande->enabled)) {
 	require DOL_DOCUMENT_ROOT . '/commande/class/commande.class.php';
@@ -87,6 +89,7 @@ $NBLINES=4;
 $usehm=(! empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE)?$conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE:0);
 
 $object=new Facture($db);
+$extrafields = new ExtraFields($db);
 
 // Load object
 if ($id > 0 || ! empty($ref))
@@ -614,6 +617,15 @@ else if ($action == 'add' && $user->rights->facture->creer)
     $db->begin();
 
     $error=0;
+    
+    // Get extra fields
+    foreach($_POST as $key => $value)
+    {
+    	if (preg_match("/^options_/",$key))
+    	{
+    		$object->array_options[$key]=GETPOST($key);
+    	}
+    }
 
     // Replacement invoice
     if ($_POST['type'] == 1)
@@ -1722,6 +1734,36 @@ if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->rights->facture-
 	}
 }
 
+if ($action == 'update_extras')
+{
+	// Get extra fields
+	foreach($_POST as $key => $value)
+	{
+		if (preg_match("/^options_/",$key))
+		{
+			$object->array_options[$key]=$_POST[$key];
+		}
+	}
+	// Actions on extra fields (by external module or standard code)
+	// FIXME le hook fait double emploi avec le trigger !!
+	$hookmanager->initHooks(array('invoicedao'));
+	$parameters=array('id'=>$object->id);
+	$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
+	if (empty($reshook))
+	{
+		if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
+		{
+			$result=$object->insertExtraFields();
+			if ($result < 0)
+			{
+				$error++;
+			}
+		}
+	}
+	else if ($reshook < 0) $error++;
+
+}
+
 
 /*
  * View
@@ -1744,6 +1786,7 @@ $now=dol_now();
 if ($action == 'create')
 {
     $facturestatic=new Facture($db);
+    $extralabels=$extrafields->fetch_name_optionals_label('facture');
 
     print_fiche_titre($langs->trans('NewBill'));
 
@@ -2221,6 +2264,10 @@ else if ($id > 0 || ! empty($ref))
      */
 
     $result=$object->fetch($id,$ref);
+    
+    // fetch optionals attributes and labels
+ 	$extralabels=$extrafields->fetch_name_optionals_label('facture');
+ 	
     if ($result > 0)
     {
         if ($user->societe_id>0 && $user->societe_id!=$object->socid)  accessforbidden('',0);
@@ -3029,21 +3076,58 @@ else if ($id > 0 || ! empty($ref))
             print '</td>';
             print '</tr>';
         }
-
+        
         // Other attributes
-        $parameters=array('colspan' => ' colspan="3"');
-        $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action);    // Note that $action and $object may have been modified by hook
+        $res=$object->fetch_optionals($object->id,$extralabels);
+        $parameters=array('colspan' => ' colspan="2"');
+        $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$object,$action); // Note that $action and $object may have been modified by hook
         if (empty($reshook) && ! empty($extrafields->attribute_label))
         {
-            foreach($extrafields->attribute_label as $key=>$label)
-            {
-                $value=(isset($_POST["options_".$key])?$_POST["options_".$key]:$object->array_options["options_".$key]);
-          		print '<tr><td';
-         		if (! empty($extrafields->attribute_required[$key])) print ' class="fieldrequired"';
-         		print '>'.$label.'</td><td colspan="3">';
-                print $extrafields->showInputField($key,$value);
-                print '</td></tr>'."\n";
-            }
+        
+        	if ($action == 'edit_extras')
+        	{
+        		print '<form enctype="multipart/form-data" action="'.$_SERVER["PHP_SELF"].'" method="post" name="formsoc">';
+        		print '<input type="hidden" name="action" value="update_extras">';
+        		print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+        		print '<input type="hidden" name="id" value="'.$object->id.'">';
+        	}
+        
+        
+        	foreach($extrafields->attribute_label as $key=>$label)
+        	{
+        		$value=(isset($_POST["options_".$key])?$_POST["options_".$key]:$object->array_options["options_".$key]);
+        		print '<tr><td';
+        		if (! empty($extrafields->attribute_required[$key])) print ' class="fieldrequired"';
+        		print '>'.$label.'</td><td colspan="5">';
+        		if ($action == 'edit_extras' && $user->rights->propal->creer)
+        		{
+        			print $extrafields->showInputField($key,$value);
+        		}
+        		else
+        		{
+        			print $extrafields->showOutputField($key,$value);
+        		}
+        
+        		print '</td></tr>'."\n";
+        	}
+        
+        	if(count($extrafields->attribute_label) > 0) {
+        
+        		if ($action == 'edit_extras' && $user->rights->propal->creer)
+        		{
+        			print '<tr><td></td><td colspan="5">';
+        			print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
+        			print '</form>';
+        			print '</td></tr>';
+        
+        		}
+        		else {
+        			if ($object->statut == 0 && $user->rights->propal->creer)
+        			{
+        				print '<tr><td></td><td><a href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=edit_extras">'.img_picto('','edit').' '.$langs->trans('Modify').'</a></td></tr>';
+        			}
+        		}
+        	}
         }
 
         print '</table><br>';
diff --git a/htdocs/compta/facture/admin/facture_cust_extrafields.php b/htdocs/compta/facture/admin/facture_cust_extrafields.php
new file mode 100644
index 0000000000000000000000000000000000000000..d08d5fe0ba83babdd181d0ddac5790590bd33d31
--- /dev/null
+++ b/htdocs/compta/facture/admin/facture_cust_extrafields.php
@@ -0,0 +1,160 @@
+<?php
+/* Copyright (C) 2001-2002 Rodolphe Quiedeville <rodolphe@quiedeville.org>
+* Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
+* Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
+* Copyright (C) 2012 Regis Houssin <regis.houssin@capnetworks.com>
+* Copyright (C) 2013 Jean-Francois FERRY <jfefe@aternatik.fr>
+*
+* 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/>.
+*/
+
+/**
+* \file htdocs/compta/facture/admin/facture_cust_extrafields.php
+* \ingroup invoice
+* \brief Page to setup extra fields of customer invoice
+*/
+
+require '../../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+
+$langs->load("companies");
+$langs->load("admin");
+$langs->load("bills");
+
+$extrafields = new ExtraFields($db);
+$form = new Form($db);
+
+// List of supported format
+$tmptype2label=getStaticMember(get_class($extrafields),'type2label');
+$type2label=array('');
+foreach ($tmptype2label as $key => $val) $type2label[$key]=$langs->trans($val);
+
+$action=GETPOST('action', 'alpha');
+$attrname=GETPOST('attrname', 'alpha');
+$elementtype='facture';
+
+if (!$user->admin) accessforbidden();
+
+
+/*
+* Actions
+*/
+
+require DOL_DOCUMENT_ROOT.'/core/admin_extrafields.inc.php';
+
+
+
+/*
+* View
+*/
+
+$textobject=strtolower($langs->transnoentitiesnoconv("BillsCustomers"));
+
+
+llxHeader('',$langs->trans("BillsSetup"));
+
+
+$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
+print_fiche_titre($langs->trans("BillsSetup"),$linkback,'setup');
+print '<br>';
+
+$head = invoice_admin_prepare_head(null);
+
+dol_fiche_head($head, 'attributes', $langs->trans("Invoices"), 0, 'invoice');
+
+
+print $langs->trans("DefineHereComplementaryAttributes",$textobject).'<br>'."\n";
+
+dol_htmloutput_errors($mesg);
+
+// Load attribute_label
+$extrafields->fetch_name_optionals_label($elementtype);
+
+print "<table summary=\"listofattributes\" class=\"noborder\" width=\"100%\">";
+
+print '<tr class="liste_titre">';
+print '<td align="center">'.$langs->trans("Position").'</td>';
+print '<td>'.$langs->trans("Label").'</td>';
+print '<td>'.$langs->trans("AttributeCode").'</td>';
+print '<td>'.$langs->trans("Type").'</td>';
+print '<td align="right">'.$langs->trans("Size").'</td>';
+print '<td align="center">'.$langs->trans("Unique").'</td>';
+print '<td align="center">'.$langs->trans("Required").'</td>';
+print '<td width="80">&nbsp;</td>';
+print "</tr>\n";
+
+$var=True;
+foreach($extrafields->attribute_type as $key => $value)
+{
+    $var=!$var;
+    print "<tr ".$bc[$var].">";
+    print "<td>".$extrafields->attribute_pos[$key]."</td>\n";
+    print "<td>".$extrafields->attribute_label[$key]."</td>\n";
+    print "<td>".$key."</td>\n";
+    print "<td>".$type2label[$extrafields->attribute_type[$key]]."</td>\n";
+    print '<td align="right">'.$extrafields->attribute_size[$key]."</td>\n";
+    print '<td align="center">'.yn($extrafields->attribute_unique[$key])."</td>\n";
+    print '<td align="center">'.yn($extrafields->attribute_required[$key])."</td>\n";
+    print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=edit&attrname='.$key.'">'.img_edit().'</a>';
+    print "&nbsp; <a href=\"".$_SERVER["PHP_SELF"]."?action=delete&attrname=$key\">".img_delete()."</a></td>\n";
+    print "</tr>";
+    // $i++;
+}
+
+print "</table>";
+
+dol_fiche_end();
+
+
+// Buttons
+if ($action != 'create' && $action != 'edit')
+{
+    print '<div class="tabsAction">';
+    print "<a class=\"butAction\" href=\"".$_SERVER["PHP_SELF"]."?action=create\">".$langs->trans("NewAttribute")."</a>";
+    print "</div>";
+}
+
+
+/* ************************************************************************** */
+/* */
+/* Creation d'un champ optionnel
+/* */
+/* ************************************************************************** */
+
+if ($action == 'create')
+{
+    print "<br>";
+    print_titre($langs->trans('NewAttribute'));
+
+    require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_add.tpl.php';
+}
+
+/* ************************************************************************** */
+/* */
+/* Edition d'un champ optionnel */
+/* */
+/* ************************************************************************** */
+if ($action == 'edit' && ! empty($attrname))
+{
+    print "<br>";
+    print_titre($langs->trans("FieldEdition", $attrname));
+
+    require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_edit.tpl.php';
+}
+
+llxFooter();
+
+$db->close();
+?>
\ No newline at end of file
diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php
index aba862202bf7785fc698370bcca2208b17842b53..ace5e15312c56c770a1807e7ad8e5fd81edd50f3 100644
--- a/htdocs/compta/facture/class/facture.class.php
+++ b/htdocs/compta/facture/class/facture.class.php
@@ -136,7 +136,7 @@ class Facture extends CommonInvoice
      */
     function create($user,$notrigger=0,$forceduedate=0)
     {
-        global $langs,$conf,$mysoc;
+        global $langs,$conf,$mysoc,$hookmanager;
         $error=0;
 
         // Clean parameters
@@ -438,6 +438,24 @@ class Facture extends CommonInvoice
                 $result=$this->update_price(1);
                 if ($result > 0)
                 {
+                	// Actions on extra fields (by external module or standard code)
+                	// FIXME le hook fait double emploi avec le trigger !!
+                	$hookmanager->initHooks(array('invoicedao'));
+                	$parameters=array('invoiceid'=>$this->id);
+                	$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
+                	if (empty($reshook))
+                	{
+                		if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
+                		{
+                			$result=$this->insertExtraFields();
+                			if ($result < 0)
+                			{
+                				$error++;
+                			}
+                		}
+                	}
+                	else if ($reshook < 0) $error++;
+                	
                     // Appel des triggers
                     include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
                     $interface=new Interfaces($this->db);
@@ -848,6 +866,20 @@ class Facture extends CommonInvoice
                 $this->extraparams			= (array) json_decode($obj->extraparams, true);
 
                 if ($this->statut == 0)	$this->brouillon = 1;
+                
+                // Retreive all extrafield for invoice
+                // fetch optionals attributes and labels
+                if(!class_exists('Extrafields'))
+                	require_once(DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php');
+                $extrafields=new ExtraFields($this->db);
+                $extralabels=$extrafields->fetch_name_optionals_label('facture',true);
+                if (count($extralabels)>0) {
+                	$this->array_options = array();
+                }
+                foreach($extrafields->attribute_label as $key=>$label)
+                {
+                	$this->array_options['options_'.$key]=$label;
+                }
 
                 /*
                  * Lines
diff --git a/htdocs/compta/facture/class/facturestats.class.php b/htdocs/compta/facture/class/facturestats.class.php
index abc0128837390f0aa1a694844b0e070ccaaf3033..f99b8f3bb272e5d2eea227ebc7ffc910fd99ed57 100644
--- a/htdocs/compta/facture/class/facturestats.class.php
+++ b/htdocs/compta/facture/class/facturestats.class.php
@@ -56,7 +56,7 @@ class FactureStats extends Stats
 		global $conf;
 
 		$this->db = $db;
-        $this->socid = $socid;
+        $this->socid = ($socid > 0 ? $socid : 0);
         $this->userid = $userid;
 
 		if ($mode == 'customer')
diff --git a/htdocs/compta/facture/stats/index.php b/htdocs/compta/facture/stats/index.php
index 968be79feb79d9f95dcf115205d3d59c8fad297a..7fc43f1edfe94443eb273baea378d3a356a1f061 100644
--- a/htdocs/compta/facture/stats/index.php
+++ b/htdocs/compta/facture/stats/index.php
@@ -34,8 +34,8 @@ $mode=GETPOST("mode")?GETPOST("mode"):'customer';
 if ($mode == 'customer' && ! $user->rights->facture->lire) accessforbidden();
 if ($mode == 'supplier' && ! $user->rights->fournisseur->facture->lire) accessforbidden();
 
-$userid=GETPOST('userid','int'); if ($userid < 0) $userid=0;
-$socid=GETPOST('socid','int'); if ($socid < 0) $socid=0;
+$userid=GETPOST('userid','int');
+$socid=GETPOST('socid','int');
 // Security check
 if ($user->societe_id > 0)
 {
diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php
index 0c0c55ebf572f3abc6786f1400005c60f336ed14..4c044314c635194412b165ef67fe1301ac2458be 100644
--- a/htdocs/compta/prelevement/class/bonprelevement.class.php
+++ b/htdocs/compta/prelevement/class/bonprelevement.class.php
@@ -540,7 +540,7 @@ class BonPrelevement extends CommonObject
                 $this->method_trans = $method;
                 $langs->load('withdrawals');
                 $subject = $langs->trans("InfoTransSubject", $this->ref);
-                $message = $langs->trans("InfoTransMessage", $this->ref, $user->firstname, $user->lastname);
+                $message = $langs->trans("InfoTransMessage", $this->ref, dolGetFirstLastname($user->firstname, $user->lastname));
                 $message .=$langs->trans("InfoTransData", price($this->amount), $this->methodes_trans[$this->method_trans], dol_print_date($date,'day'));
 
                 // TODO Call trigger to create a notification using notification module
diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php
index 4f0a029993f9211c2b60f649b9e52e051ede77d5..faccaa315459174f935fb2bc3f3cf72e6cda2942 100755
--- a/htdocs/core/class/commondocgenerator.class.php
+++ b/htdocs/core/class/commondocgenerator.class.php
@@ -161,18 +161,18 @@ abstract class CommonDocGenerator
             'company_idprof4'=>$object->idprof4,
             'company_idprof5'=>$object->idprof5,
             'company_idprof6'=>$object->idprof6,
-        	'company_note'=>$object->note
+            'company_note'=>$object->note
         );
 
         // Retrieve extrafields
         if(is_array($object->array_options) && count($object->array_options))
         {
-      		if(!class_exists('Extrafields'))
+        	if(!class_exists('Extrafields'))
         		require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
         	$extrafields = new ExtraFields($this->db);
         	$extralabels = $extrafields->fetch_name_optionals_label('company',true);
         	$object->fetch_optionals($object->id,$extralabels);
-        	 
+
         	foreach($extrafields->attribute_label as $key=>$label)
         	{
         		if($extrafields->attribute_type[$key] == 'price')
@@ -180,7 +180,7 @@ abstract class CommonDocGenerator
         			$object->array_options['options_'.$key] = price($object->array_options['options_'.$key]).' '.$outputlangs->getCurrencySymbol($conf->currency);
         		}
         		else if($extrafields->attribute_type[$key] == 'select')
-        		{        			
+        		{
         			$object->array_options['options_'.$key] = $extrafields->attribute_param[$key]['options'][$object->array_options['options_'.$key]];
         		}
         		$array_thirdparty=array_merge($array_thirdparty,array('company_options_'.$key => $object->array_options['options_'.$key]));
@@ -189,6 +189,134 @@ abstract class CommonDocGenerator
         return $array_thirdparty;
     }
 
+    
+    /**
+     * Define array with couple substitution key => substitution value
+     *
+     * @param   Object			$object             Main object to use as data source
+     * @param   Translate		$outputlangs        Lang object to use for output
+     * @param   array_key		$array_key	        Name of the key for return array
+     * @return	array								Array of substitution
+     */
+    function get_substitutionarray_propal($object,$outputlangs,$array_key='object')
+    {
+    	global $conf;
+    
+    	$array_propal=array(
+	    	$array_key.'_id'=>$object->id,
+	    	$array_key.'_ref'=>$object->ref,
+	    	$array_key.'_ref_ext'=>$object->ref_ext,
+	    	$array_key.'_ref_customer'=>$object->ref_client,
+	    	$array_key.'_date'=>dol_print_date($object->date,'day'),
+	    	$array_key.'_date_end'=>dol_print_date($object->fin_validite,'day'),
+	    	$array_key.'_date_creation'=>dol_print_date($object->date_creation,'day'),
+	    	$array_key.'_date_modification'=>dol_print_date($object->date_modification,'day'),
+	    	$array_key.'_date_validation'=>dol_print_date($object->date_validation,'dayhour'),
+	    	$array_key.'_payment_mode_code'=>$object->mode_reglement_code,
+	    	$array_key.'_payment_mode'=>($outputlangs->transnoentitiesnoconv('PaymentType'.$object->mode_reglement_code)!='PaymentType'.$object->mode_reglement_code?$outputlangs->transnoentitiesnoconv('PaymentType'.$object->mode_reglement_code):$object->mode_reglement),
+	    	$array_key.'_payment_term_code'=>$object->cond_reglement_code,
+	    	$array_key.'_payment_term'=>($outputlangs->transnoentitiesnoconv('PaymentCondition'.$object->cond_reglement_code)!='PaymentCondition'.$object->cond_reglement_code?$outputlangs->transnoentitiesnoconv('PaymentCondition'.$object->cond_reglement_code):$object->cond_reglement),
+	    	$array_key.'_total_ht'=>price2num($object->total_ht2,2),
+	    	$array_key.'_total_vat'=>price2num($object->total_tva,2),
+	    	$array_key.'_total_ttc'=>price2num($object->total_ttc,2),
+	    	$array_key.'_total_discount_ht' => price2num($object->getTotalDiscount(),2),
+	    	$array_key.'_vatrate'=>vatrate($object->tva),
+	    	$array_key.'_note_private'=>$object->note,
+	    	$array_key.'_note'=>$object->note_public,
+    	);
+    
+    	// Add vat by rates
+    	foreach ($object->lines as $line)
+    	{
+    		if (empty($array_propal[$array_key.'_total_vat_'.$line->tva_tx])) $array_propal[$array_key.'_total_vat_'.$line->tva_tx]=0;
+    		$array_propal[$array_key.'_total_vat_'.$line->tva_tx]+=$line->total_tva;
+    	}
+    	
+    	// Retrieve extrafields
+    	if(is_array($object->array_options) && count($object->array_options))
+    	{
+    		if(!class_exists('Extrafields'))
+    			require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+    		$extrafields = new ExtraFields($this->db);
+    		$extralabels = $extrafields->fetch_name_optionals_label('propal',true);
+    		$object->fetch_optionals($object->id,$extralabels);
+    	
+    		$array_propal = $this->fill_substitutionarray_with_extrafields($object,$array_propal,$extrafields,$array_key,$outputlangs);
+    	}
+    	return $array_propal;
+    }
+    
+
+    /**
+     *	Define array with couple substitution key => substitution value
+     *
+     *	@param  array			$line				Array of lines
+     *	@param  Translate		$outputlangs        Lang object to use for output
+     *	@return	array								Substitution array
+     */
+    function get_substitutionarray_propal_lines($line,$outputlangs)
+    {
+    	global $conf;
+    
+    	return array(
+    	'line_fulldesc'=>doc_getlinedesc($line,$outputlangs),
+    	'line_product_ref'=>$line->product_ref,
+    	'line_product_label'=>$line->product_label,
+    	'line_desc'=>$line->desc,
+    	'line_vatrate'=>vatrate($line->tva_tx,true,$line->info_bits),
+    	'line_up'=>price2num($line->subprice, 2),
+    	'line_qty'=>$line->qty,
+    	'line_discount_percent'=>($line->remise_percent?$line->remise_percent.'%':''),
+    	'line_price_ht'=>price2num($line->total_ht,2),
+    	'line_price_ttc'=>price2num($line->total_ttc,2),
+    	'line_price_vat'=>price2num($line->total_tva,2),
+    	'line_date_start'=>$line->date_start,
+    	'line_date_end'=>$line->date_end
+    	);
+    }
+    
+    /**
+     *	Fill array with couple extrafield key => extrafield value
+     *
+     *	@param  Object			$object				Object with extrafields (must have $object->array_options filled)
+     *	@param  array			$array_to_fill      Substitution array
+     *  @param  Extrafields		$extrafields        Extrafields object
+     *  @param   array_key		$array_key	        Name of the key for return array
+     *  @param  Translate		$outputlangs        Lang object to use for output
+     *	@return	array								Substitution array
+     */
+	function fill_substitutionarray_with_extrafields($object,$array_to_fill,$extrafields,$array_key,$outputlangs)
+	{
+		global $conf;
+		foreach($extrafields->attribute_label as $key=>$label)
+		{
+			if($extrafields->attribute_type[$key] == 'price')
+			{
+				$object->array_options['options_'.$key] = price2num($object->array_options['options_'.$key],2);
+				$object->array_options['options_'.$key.'_currency'] = $object->array_options['options_'.$key].' '.$outputlangs->getCurrencySymbol($conf->currency);
+				//Add value to store price with currency
+				$array_to_fill=array_merge($array_to_fill,array($array_key.'_options_'.$key.'_currency' => $object->array_options['options_'.$key.'_currency']));
+			}
+			else if($extrafields->attribute_type[$key] == 'select')
+			{
+				$object->array_options['options_'.$key] = $extrafields->attribute_param[$key]['options'][$object->array_options['options_'.$key]];
+			}
+			else if($extrafields->attribute_type[$key] == 'date')
+			{
+				$object->array_options['options_'.$key] = (strlen($object->array_options['options_'.$key])>0?dol_print_date($object->array_options['options_'.$key],'day'):'');
+			}
+			else if($extrafields->attribute_type[$key] == 'datetime')
+			{
+				$object->array_options['options_'.$key] = ($object->array_options['options_'.$key]!="0000-00-00 00:00:00"?dol_print_date($object->array_options['options_'.$key],'dayhour'):'');
+			}
+			$array_to_fill=array_merge($array_to_fill,array($array_key.'_options_'.$key => $object->array_options['options_'.$key]));    			
+		}
+		
+		return $array_to_fill;
+	    	
+	}
+    
+    
 	/**
 	 * Rect pdf
 	 *
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index 5865566675533dcead7a08ca1c2def7aceef6438..50bd564e8d9b2c66720167483615bdb598715372 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -73,21 +73,8 @@ abstract class CommonObject
             else $ret.=$this->civilite_id.' ';
         }
 
-        // If order not defined, we use the setup
-        if ($nameorder < 0) $nameorder=(empty($conf->global->MAIN_FIRSTNAME_NAME_POSITION));
+        $ret.=dolGetFirstLastname($firstname, $lastname, $nameorder);
 
-        if ($nameorder)
-        {
-            $ret.=$firstname;
-            if ($firstname && $lastname) $ret.=' ';
-            $ret.=$lastname;
-        }
-        else
-        {
-            $ret.=$lastname;
-            if ($firstname && $lastname) $ret.=' ';
-            $ret.=$firstname;
-        }
         return dol_trunc($ret,$maxlen);
     }
 
diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php
index f72ddc8d6e211d301ad2d376a4dcbf1cc8f6a997..de828e8a2374311aedc4c3ac68c7427826d481aa 100755
--- a/htdocs/core/class/extrafields.class.php
+++ b/htdocs/core/class/extrafields.class.php
@@ -651,9 +651,11 @@ class ExtraFields
         elseif ($type == 'select')
         {
         	$out='<select name="options_'.$key.'">';
-        	foreach ($param['options'] as $key=>$value )
+        	foreach ($param['options'] as $key=>$val )
         	{
-        		$out.='<option value="'.$key.'">'.$value.'</option>';
+        		$out.='<option value="'.$key.'"';
+        		$out.= ($value==$key?'selected="selected"':'');
+        		$out.='>'.$val.'</option>';
         	}
         	$out.='</select>';
         }
diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php
index eb34a3913ceaca4576f9ac0bb81f2edbadc88656..9e8a47812fd3967a3d6b2d4b8aa1c93d36df96b4 100644
--- a/htdocs/core/class/html.formfile.class.php
+++ b/htdocs/core/class/html.formfile.class.php
@@ -194,7 +194,7 @@ class FormFile
      *      @param      boolean             $printer            Printer Icon
      * 		@return		string              					Output string with HTML array of documents (might be empty string)
      */
-    function showdocuments($modulepart,$filename,$filedir,$urlsource,$genallowed,$delallowed=0,$modelselected='',$allowgenifempty=1,$forcenomultilang=0,$iconPDF=0,$maxfilenamelength=28,$noform=0,$param='',$title='',$buttonlabel='',$codelang='',$printer)
+    function showdocuments($modulepart,$filename,$filedir,$urlsource,$genallowed,$delallowed=0,$modelselected='',$allowgenifempty=1,$forcenomultilang=0,$iconPDF=0,$maxfilenamelength=28,$noform=0,$param='',$title='',$buttonlabel='',$codelang='',$printer=false)
     {
         // filedir = conf->...dir_ouput."/".get_exdir(id)
         include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 817396f97fcf51911349aa85262011fb56262e15..3acf7983fe3e4ed68c7705462ba6aa1dde1a7631 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -3643,13 +3643,29 @@ function get_date_range($date_start,$date_end,$format = '',$outputlangs='')
  *
  * @param	string	$firstname		Firstname
  * @param	string	$lastname		Lastname
+ * @param	int		$nameorder		-1=Auto, 0=Lastname+Firstname, 1=Firstname+Lastname
  * @return	string					Firstname + lastname or Lastname + firstname
  */
-function dolGetFirstLastname($firstname,$lastname)
+function dolGetFirstLastname($firstname,$lastname,$nameorder=-1)
 {
 	global $conf;
-	if (empty($conf->global->MAIN_FIRSTNAME_NAME_POSITION)) return $firstname.' '.$lastname;
-	else return $lastname.' '.$firstname;
+
+	$ret='';
+	// If order not defined, we use the setup
+	if ($nameorder < 0) $nameorder=(empty($conf->global->MAIN_FIRSTNAME_NAME_POSITION));
+	if ($nameorder)
+	{
+		$ret.=$firstname;
+		if ($firstname && $lastname) $ret.=' ';
+		$ret.=$lastname;
+	}
+	else
+	{
+		$ret.=$lastname;
+		if ($firstname && $lastname) $ret.=' ';
+		$ret.=$firstname;
+	}
+	return $ret;
 }
 
 
diff --git a/htdocs/core/lib/invoice.lib.php b/htdocs/core/lib/invoice.lib.php
index e70f215df2d3326a5979e098d44e6de78ccf6c46..03b8fa7240d9a3451290e1868eed55a0c5f7e730 100644
--- a/htdocs/core/lib/invoice.lib.php
+++ b/htdocs/core/lib/invoice.lib.php
@@ -98,4 +98,42 @@ function facture_prepare_head($object)
 	return $head;
 }
 
+/**
+ * Return array head with list of tabs to view object informations.
+ *
+ * @param Object $object Invoice
+ * @return array head array with tabs
+ */
+function invoice_admin_prepare_head($object)
+{
+	global $langs, $conf, $user;
+
+	$h = 0;
+	$head = array();
+
+	$head[$h][0] = DOL_URL_ROOT.'/admin/facture.php';
+	$head[$h][1] = $langs->trans("Miscellanous");
+	$head[$h][2] = 'general';
+	$h++;
+
+	// Show more tabs from modules
+	// Entries must be declared in modules descriptor with line
+	// $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
+	// $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab
+	complete_head_from_modules($conf,$langs,$object,$head,$h,'invoice_admin');
+
+	$head[$h][0] = DOL_URL_ROOT.'/compta/facture/admin/facture_cust_extrafields.php';
+	$head[$h][1] = $langs->trans("ExtraFieldsCustomerInvoices");
+	$head[$h][2] = 'attributes';
+	$h++;
+
+
+
+	complete_head_from_modules($conf,$langs,$object,$head,$h,'invoice_admin','remove');
+
+	return $head;
+}
+
+
+
 ?>
\ No newline at end of file
diff --git a/htdocs/core/lib/propal.lib.php b/htdocs/core/lib/propal.lib.php
index 92eb5e27459f0d1ae4542b4f331e97be5a54c630..d6348bdcb0e90555d8f41bc97eb1f7d8568958ba 100644
--- a/htdocs/core/lib/propal.lib.php
+++ b/htdocs/core/lib/propal.lib.php
@@ -103,5 +103,41 @@ function propal_prepare_head($object)
 	return $head;
 }
 
+/**
+ *  Return array head with list of tabs to view object informations.
+ *
+ *  @param	Object	$object		Propal
+ *  @return	array   	        head array with tabs
+ */
+function propal_admin_prepare_head($object)
+{
+	global $langs, $conf, $user;
+
+	$h = 0;
+	$head = array();
+
+	$head[$h][0] = DOL_URL_ROOT.'/admin/propal.php';
+	$head[$h][1] = $langs->trans("Miscellanous");
+	$head[$h][2] = 'general';
+	$h++;
+
+	// Show more tabs from modules
+	// Entries must be declared in modules descriptor with line
+	// $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__');   to add new tab
+	// $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__');   to remove a tab
+	complete_head_from_modules($conf,$langs,$object,$head,$h,'propal_admin');
+
+	$head[$h][0] = DOL_URL_ROOT.'/comm/admin/propal_extrafields.php';
+	$head[$h][1] = $langs->trans("ExtraFields");
+    $head[$h][2] = 'attributes';
+    $h++;
+
+	
+
+	complete_head_from_modules($conf,$langs,$object,$head,$h,'propal_admin','remove');
+
+		return $head;
+}
+
 
 ?>
\ No newline at end of file
diff --git a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php
index dc00f4370fa948bed9b75731b45827cb6a14e63b..957b5d85428bf5f01a8ba43f1f1a7ec4438f0671 100644
--- a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php
+++ b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php
@@ -121,16 +121,16 @@ class doc_generic_invoice_odt extends ModelePDFFactures
         	'object_payment_mode'=>($outputlangs->transnoentitiesnoconv('PaymentType'.$object->mode_reglement_code)!='PaymentType'.$object->mode_reglement_code?$outputlangs->transnoentitiesnoconv('PaymentType'.$object->mode_reglement_code):$object->mode_reglement),
         	'object_payment_term_code'=>$object->cond_reglement_code,
         	'object_payment_term'=>($outputlangs->transnoentitiesnoconv('PaymentCondition'.$object->cond_reglement_code)!='PaymentCondition'.$object->cond_reglement_code?$outputlangs->transnoentitiesnoconv('PaymentCondition'.$object->cond_reglement_code):$object->cond_reglement),
-        	'object_total_ht'=>price($object->total_ht,0,$outputlangs),
-            'object_total_vat'=>price($object->total_tva,0,$outputlangs),
-            'object_total_ttc'=>price($object->total_ttc,0,$outputlangs),
-            'object_total_discount_ht' => price($object->getTotalDiscount(), 0, $outputlangs),
+        	'object_total_ht'=>price2num($object->total_ht,2),
+            'object_total_vat'=>price2num($object->total_tva,2),
+            'object_total_ttc'=>price2num($object->total_ttc,2),
+            'object_total_discount_ht' => price2num($object->getTotalDiscount(), 0, $outputlangs),
             'object_vatrate'=>(isset($object->tva)?vatrate($object->tva):''),
             'object_note_private'=>$object->note,
             'object_note'=>$object->note_public,
         	// Payments
             'object_already_payed'=>$alreadypayed,
-            'object_remain_to_pay'=>price($object->total_ttc - $sumpayed,0,$outputlangs)
+            'object_remain_to_pay'=>price2num($object->total_ttc - $sumpayed,2)
         );
 
         // Add vat by rates
@@ -140,6 +140,17 @@ class doc_generic_invoice_odt extends ModelePDFFactures
 			$resarray['object_total_vat_'.$line->tva_tx]+=$line->total_tva;
 		}
 		
+		// Retrieve extrafields
+		if(is_array($object->array_options) && count($object->array_options))
+		{
+			if(!class_exists('Extrafields'))
+				require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+			$extrafields = new ExtraFields($this->db);
+			$extralabels = $extrafields->fetch_name_optionals_label('facture',true);
+			$object->fetch_optionals($object->id,$extralabels);
+		
+			$resarray = $this->fill_substitutionarray_with_extrafields($object,$resarray,$extrafields,$array_key='object',$outputlangs);
+		}
         return $resarray;
     }
 
@@ -163,9 +174,9 @@ class doc_generic_invoice_odt extends ModelePDFFactures
             'line_up'=>price($line->subprice, 0, $outputlangs),
             'line_qty'=>$line->qty,
             'line_discount_percent'=>($line->remise_percent?$line->remise_percent.'%':''),
-            'line_price_ht'=>price($line->total_ht, 0, $outputlangs),
-            'line_price_ttc'=>price($line->total_ttc, 0, $outputlangs),
-            'line_price_vat'=>price($line->total_tva, 0, $outputlangs),
+            'line_price_ht'=>price2num($line->total_ht, 2),
+            'line_price_ttc'=>price2num($line->total_ttc, 2),
+            'line_price_vat'=>price2num($line->total_tva, 2),
             'line_date_start'=>dol_print_date($line->date_start, 'day', false, $outputlangs),
             'line_date_end'=>dol_print_date($line->date_end, 'day', false, $outputlangs),
         );
@@ -347,7 +358,14 @@ class doc_generic_invoice_odt extends ModelePDFFactures
                 {
                     $socobject=$object->client;
                 }
-
+                
+                // Fetch info for linked propal
+                $linked_propal = $object->fetchObjectLinked('','','','');
+                print '<pre>';
+                //print_r($object->linkedObjects['propal']); exit;
+
+                $propal_object = $object->linkedObjects['propal'][0];
+                
                 // Make substitution
                 $substitutionarray=array(
                     '__FROM_NAME__' => $this->emetteur->nom,
@@ -397,8 +415,9 @@ class doc_generic_invoice_odt extends ModelePDFFactures
 				$array_soc=$this->get_substitutionarray_mysoc($mysoc,$outputlangs);
 				$array_thirdparty=$this->get_substitutionarray_thirdparty($socobject,$outputlangs);
 				$array_objet=$this->get_substitutionarray_object($object,$outputlangs);
+				$array_propal=$this->get_substitutionarray_propal($propal_object,$outputlangs,'propal');
 
-				$tmparray = array_merge($array_user,$array_soc,$array_thirdparty,$array_objet);
+				$tmparray = array_merge($array_user,$array_soc,$array_thirdparty,$array_objet,$array_propal);
 				complete_substitutions_array($tmparray, $outputlangs, $object);
 
                 //var_dump($tmparray); exit;
diff --git a/htdocs/core/modules/modBanque.class.php b/htdocs/core/modules/modBanque.class.php
index ba00c90faca14ad41d77893eb4f4970acce0b04e..1bae9f6112925af9e2b1f2cb4580ed671918d1e8 100644
--- a/htdocs/core/modules/modBanque.class.php
+++ b/htdocs/core/modules/modBanque.class.php
@@ -159,7 +159,7 @@ class modBanque extends DolibarrModules
 		$this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON bu.url_id = s.rowid';
 		$this->export_sql_end[$r] .=' WHERE ba.rowid = b.fk_account';
 		$this->export_sql_end[$r] .=' AND ba.entity = '.$conf->entity;
-		$this->export_sql_end[$r] .=' ORDER BY b.datev, b.num_releve';
+		$this->export_sql_order[$r] .=' ORDER BY b.datev, b.num_releve';
 	}
 
 
diff --git a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php
index e6103f5a8021c2ac73104a64f0e556febec5da58..0f9e64c1fe20248eb4602540eb4bb76a75db77a0 100644
--- a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php
+++ b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php
@@ -86,78 +86,6 @@ class doc_generic_proposal_odt extends ModelePDFPropales
 	}
 
 
-    /**
-     * Define array with couple substitution key => substitution value
-     *
-     * @param   Object			$object             Main object to use as data source
-     * @param   Translate		$outputlangs        Lang object to use for output
-     * @return	array								Array of substitution
-     */
-    function get_substitutionarray_object($object,$outputlangs)
-    {
-        global $conf;
-
-        $resarray=array(
-            'object_id'=>$object->id,
-            'object_ref'=>$object->ref,
-            'object_ref_ext'=>$object->ref_ext,
-        	'object_ref_customer'=>$object->ref_client,
-        	'object_date'=>dol_print_date($object->date,'day'),
-        	'object_date_end'=>dol_print_date($object->fin_validite,'day'),
-        	'object_date_creation'=>dol_print_date($object->date_creation,'day'),
-            'object_date_modification'=>dol_print_date($object->date_modification,'day'),
-            'object_date_validation'=>dol_print_date($object->date_validation,'dayhour'),
-            'object_payment_mode_code'=>$object->mode_reglement_code,
-        	'object_payment_mode'=>($outputlangs->transnoentitiesnoconv('PaymentType'.$object->mode_reglement_code)!='PaymentType'.$object->mode_reglement_code?$outputlangs->transnoentitiesnoconv('PaymentType'.$object->mode_reglement_code):$object->mode_reglement),
-        	'object_payment_term_code'=>$object->cond_reglement_code,
-        	'object_payment_term'=>($outputlangs->transnoentitiesnoconv('PaymentCondition'.$object->cond_reglement_code)!='PaymentCondition'.$object->cond_reglement_code?$outputlangs->transnoentitiesnoconv('PaymentCondition'.$object->cond_reglement_code):$object->cond_reglement),
-        	'object_total_ht'=>price($object->total_ht,0,$outputlangs),
-            'object_total_vat'=>price($object->total_tva,0,$outputlangs),
-            'object_total_ttc'=>price($object->total_ttc,0,$outputlangs),
-            'object_total_discount_ht' => price($object->getTotalDiscount(), 0, $outputlangs),
-            'object_vatrate'=>vatrate($object->tva),
-            'object_note_private'=>$object->note,
-            'object_note'=>$object->note_public,
-        );
-        
-        // Add vat by rates
-        foreach ($object->lines as $line)
-        {
-        	if (empty($resarray['object_total_vat_'.$line->tva_tx])) $resarray['object_total_vat_'.$line->tva_tx]=0;
-        	$resarray['object_total_vat_'.$line->tva_tx]+=$line->total_tva;
-        }
-        
-        return $resarray;
-    }
-
-    /**
-     *	Define array with couple substitution key => substitution value
-     *
-     *	@param  array			$line				Array of lines
-     *	@param  Translate		$outputlangs        Lang object to use for output
-     *	@return	array								Substitution array
-     */
-    function get_substitutionarray_lines($line,$outputlangs)
-    {
-        global $conf;
-
-        return array(
-            'line_fulldesc'=>doc_getlinedesc($line,$outputlangs),
-            'line_product_ref'=>$line->product_ref,
-            'line_product_label'=>$line->product_label,
-            'line_desc'=>$line->desc,
-            'line_vatrate'=>vatrate($line->tva_tx,true,$line->info_bits),
-            'line_up'=>price($line->subprice, 0, $outputlangs),
-            'line_qty'=>$line->qty,
-            'line_discount_percent'=>($line->remise_percent?$line->remise_percent.'%':''),
-            'line_price_ht'=>price($line->total_ht, 0, $outputlangs),
-            'line_price_ttc'=>price($line->total_ttc, 0, $outputlangs),
-            'line_price_vat'=>price($line->total_tva, 0, $outputlangs),
-            'line_date_start'=>$line->date_start,
-            'line_date_end'=>$line->date_end
-        );
-    }
-
 	/**
 	 *	Return description of a module
 	 *
@@ -441,7 +369,8 @@ class doc_generic_proposal_odt extends ModelePDFPropales
 					}
 				}
 				// Replace tags of object + external modules
-			    $tmparray=$this->get_substitutionarray_object($object,$outputlangs);
+			    $tmparray=$this->get_substitutionarray_propal($object,$outputlangs);
+			    //print_r($tmparray); exit;
 			    complete_substitutions_array($tmparray, $outputlangs, $object);
                 foreach($tmparray as $key=>$value)
                 {
@@ -466,7 +395,7 @@ class doc_generic_proposal_odt extends ModelePDFPropales
                     $listlines = $odfHandler->setSegment('lines');
                     foreach ($object->lines as $line)
                     {
-                        $tmparray=$this->get_substitutionarray_lines($line,$outputlangs);
+                        $tmparray=$this->get_substitutionarray_propal_lines($line,$outputlangs);
                         complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines");
                         foreach($tmparray as $key => $val)
                         {
diff --git a/htdocs/exports/class/export.class.php b/htdocs/exports/class/export.class.php
index 6a51380e8a159a9db8688610e1b905a7f73ae800..f850c20d07f3363693a2bd79160ac2f683192bbd 100644
--- a/htdocs/exports/class/export.class.php
+++ b/htdocs/exports/class/export.class.php
@@ -34,7 +34,9 @@ class Export
 	var $array_export_code=array();             // Tableau de "idmodule_numlot"
 	var $array_export_module=array();           // Tableau de "nom de modules"
 	var $array_export_label=array();            // Tableau de "libelle de lots"
-	var $array_export_sql=array();              // Tableau des "requetes sql"
+	var $array_export_sql_start=array();        // Tableau des "requetes sql"
+	var $array_export_sql_end=array();          // Tableau des "requetes sql"
+	var $array_export_sql_order=array();        // Tableau des "requetes sql"
 	var $array_export_fields=array();           // Tableau des listes de champ+libelle a exporter
 	var $array_export_TypeFields=array();		// Tableau des listes de champ+Type de filtre
 	var $array_export_FilterValue=array();		// Tableau des listes de champ+Valeur a filtrer
@@ -177,6 +179,7 @@ class Export
 									// Requete sql du dataset
 									$this->array_export_sql_start[$i]=$module->export_sql_start[$r];
 									$this->array_export_sql_end[$i]=$module->export_sql_end[$r];
+									$this->array_export_sql_order[$i]=$module->export_sql_order[$r];
 									//$this->array_export_sql[$i]=$module->export_sql[$r];
 
 									dol_syslog(get_class($this)."::load_arrays loaded for module ".$modulename." with index ".$i.", dataset=".$module->export_code[$r].", nb of fields=".(! empty($module->export_fields_code[$r])?count($module->export_fields_code[$r]):''));
@@ -234,7 +237,8 @@ class Export
 			}
 			$sql.=$sqlWhere;
 		}
-
+		$sql.=$this->array_export_sql_order[$indice];
+		
 		return $sql;
 	}
 
diff --git a/htdocs/holiday/fiche.php b/htdocs/holiday/fiche.php
index 8602163b583a783313141595bf4c6a6043499958..518a83908c4a6fd83a5e9848a4a179c6e383317d 100644
--- a/htdocs/holiday/fiche.php
+++ b/htdocs/holiday/fiche.php
@@ -319,7 +319,7 @@ if ($action == 'confirm_send')
             }
 
             $message.= "\n";
-            $message.= "- ".$langs->transnoentitiesnoconv("Name")." : ".$expediteur->firstname." ".$expediteur->lastname."\n";
+            $message.= "- ".$langs->transnoentitiesnoconv("Name")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."\n";
             $message.= "- ".$langs->transnoentitiesnoconv("Period")." : ".dol_print_date($cp->date_debut,'day')." ".$langs->transnoentitiesnoconv("To")." ".dol_print_date($cp->date_fin,'day')."\n";
             $message.= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/fiche.php?id=".$cp->rowid."\n\n";
             $message.= "\n";
@@ -400,7 +400,7 @@ if($action == 'confirm_valid')
             $message = $langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",\n";
             $message.= "\n";
             $message.= "Votre demande de congés payés du ".dol_print_date($cp->date_debut,'day')." au ".dol_print_date($cp->date_fin,'day')." vient d'être validée!\n";
-            $message.= "- ".$langs->transnoentitiesnoconv("ValidatedBy")." : ".$expediteur->firstname." ".$expediteur->lastname."\n";
+            $message.= "- ".$langs->transnoentitiesnoconv("ValidatedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."\n";
             $message.= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/fiche.php?id=".$cp->rowid."\n\n";
             $message.= "\n";
 
@@ -469,7 +469,7 @@ if ($action == 'confirm_refuse')
 	            $message.= "\n";
                 $message.= "Votre demande de congés payés ".dol_print_date($cp->date_debut,'day')." ".$langs->transnoentitiesnoconv("To")." ".dol_print_date($cp->date_fin,'day')." vient d'être refusée pour le motif suivant :\n";
                 $message.= $_POST['detail_refuse']."\n\n";
-	            $message.= "- ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".$expediteur->firstname." ".$expediteur->lastname."\n";
+	            $message.= "- ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."\n";
     	        $message.= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/fiche.php?id=".$cp->rowid."\n\n";
                 $message.= "\n";
 
@@ -539,7 +539,7 @@ if ($action == 'confirm_cancel' && $_GET['confirm'] == 'yes')
            	$message = $langs->transnoentitiesnoconv("Hello")." ".$destinataire->firstname.",\n";
             $message.= "\n";
             $message.= "Votre demande de congés ".dol_print_date($cp->date_debut,'day')." ".$langs->transnoentitiesnoconv("To")." ".dol_print_date($cp->date_fin,'day')." va été annulée.\n";
-            $message.= "- ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".$expediteur->firstname." ".$expediteur->lastname."\n";
+            $message.= "- ".$langs->transnoentitiesnoconv("ModifiedBy")." : ".dolGetFirstLastname($expediteur->firstname, $expediteur->lastname)."\n";
    	        $message.= "- ".$langs->transnoentitiesnoconv("Link")." : ".$dolibarr_main_url_root."/holiday/fiche.php?id=".$cp->rowid."\n\n";
             $message.= "\n";
 
diff --git a/htdocs/install/mysql/migration/3.3.0-3.4.0.sql b/htdocs/install/mysql/migration/3.3.0-3.4.0.sql
index 1e5cb707753f8e6a6881a99e99ec73eada9af647..df178f1ccabacb1745fe39a21520536f7ca7d967 100755
--- a/htdocs/install/mysql/migration/3.3.0-3.4.0.sql
+++ b/htdocs/install/mysql/migration/3.3.0-3.4.0.sql
@@ -89,6 +89,23 @@ ALTER TABLE llx_c_shipment_mode CHANGE COLUMN rowid rowid INTEGER NOT NULL;
 
 ALTER TABLE llx_stock_mouvement MODIFY COLUMN value real;
 
+create table llx_propal_extrafields
+(
+  rowid                     integer AUTO_INCREMENT PRIMARY KEY,
+  tms                       timestamp,
+  fk_object                 integer NOT NULL,
+  import_key                varchar(14)                          		-- import key
+) ENGINE=innodb;
+ALTER TABLE llx_propal_extrafields ADD INDEX idx_propal_extrafields (fk_object);
+
+create table llx_facture_extrafields
+(
+  rowid integer AUTO_INCREMENT PRIMARY KEY,
+  tms timestamp,
+  fk_object integer NOT NULL,
+  import_key varchar(14) -- import key
+) ENGINE=innodb;
+ALTER TABLE llx_facture_extrafields ADD INDEX idx_facture_extrafields (fk_object);
 ALTER TABLE llx_facture ADD COLUMN revenuestamp double(24,8) DEFAULT 0 AFTER localtax2;
 
 CREATE TABLE llx_c_revenuestamp
diff --git a/htdocs/install/mysql/tables/llx_facture_extrafields.key.sql b/htdocs/install/mysql/tables/llx_facture_extrafields.key.sql
new file mode 100755
index 0000000000000000000000000000000000000000..e44905ccc2ec598f36841318caaa75c38b37a8e6
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_facture_extrafields.key.sql
@@ -0,0 +1,20 @@
+-- ===================================================================
+-- Copyright (C) 2013 Jean-Francois FERRY	<jfefe@aternatik.fr>
+--
+-- 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/>.
+--
+-- ===================================================================
+
+
+ALTER TABLE llx_facture_extrafields ADD INDEX idx_facture_extrafields (fk_object);
diff --git a/htdocs/install/mysql/tables/llx_facture_extrafields.sql b/htdocs/install/mysql/tables/llx_facture_extrafields.sql
new file mode 100755
index 0000000000000000000000000000000000000000..9ef15f4e01232345a6351d4ccab563a78b321bde
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_facture_extrafields.sql
@@ -0,0 +1,26 @@
+-- ========================================================================
+-- Copyright (C) 2013 Jean-Francois FERRY	<jfefe@aternatik.fr>
+--
+-- 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/>.
+--
+-- ========================================================================
+
+create table llx_facture_extrafields
+(
+  rowid                     integer AUTO_INCREMENT PRIMARY KEY,
+  tms                       timestamp,
+  fk_object                 integer NOT NULL,
+  import_key                varchar(14)                          		-- import key
+) ENGINE=innodb;
+
diff --git a/htdocs/install/mysql/tables/llx_propal_extrafields.key.sql b/htdocs/install/mysql/tables/llx_propal_extrafields.key.sql
new file mode 100755
index 0000000000000000000000000000000000000000..5c9cc922667882d13b29f5cf61e01201e7f8fe58
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_propal_extrafields.key.sql
@@ -0,0 +1,20 @@
+-- ===================================================================
+-- Copyright (C) 2011 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/>.
+--
+-- ===================================================================
+
+
+ALTER TABLE llx_propal_extrafields ADD INDEX idx_propal_extrafields (fk_object);
diff --git a/htdocs/install/mysql/tables/llx_propal_extrafields.sql b/htdocs/install/mysql/tables/llx_propal_extrafields.sql
new file mode 100755
index 0000000000000000000000000000000000000000..c285df56dd7999c15846c313273309f205bdf407
--- /dev/null
+++ b/htdocs/install/mysql/tables/llx_propal_extrafields.sql
@@ -0,0 +1,26 @@
+-- ========================================================================
+-- Copyright (C) 2011 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/>.
+--
+-- ========================================================================
+
+create table llx_propal_extrafields
+(
+  rowid                     integer AUTO_INCREMENT PRIMARY KEY,
+  tms                       timestamp,
+  fk_object                 integer NOT NULL,
+  import_key                varchar(14)                          		-- import key
+) ENGINE=innodb;
+
diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang
index e2048918de6748c52fd7dcd28190d871af22c31f..382db00079652fe8a080f98f059c00e8bef623ea 100644
--- a/htdocs/langs/en_US/admin.lang
+++ b/htdocs/langs/en_US/admin.lang
@@ -931,7 +931,7 @@ MAIN_PROXY_HOST=Name/Address of proxy server
 MAIN_PROXY_PORT=Port of proxy server
 MAIN_PROXY_USER=Login to use the proxy server
 MAIN_PROXY_PASS=Password to use the proxy server
-DefineHereComplementaryAttributes=Define here all atributes, not already available by default, and that you want to be supported for %s.
+DefineHereComplementaryAttributes=Define here all attributes, not already available by default, and that you want to be supported for %s.
 ExtraFields=Complementary attributes
 ExtraFieldsThirdParties=Complementary attributes (thirdparty)
 ExtraFieldsContacts=Complementary attributes (contact/address)
@@ -977,7 +977,7 @@ NotificationsDesc=EMails notifications feature allows you to silently send autom
 ModelModules=Documents templates
 DocumentModelOdt=Generate documents from OpenDocuments templates (.ODT files for OpenOffice, KOffice, TextEdit,...)
 WatermarkOnDraft=Watermark on draft document
-CompanyIdProfChecker=Rules ono Professional Ids
+CompanyIdProfChecker=Rules on Professional Ids
 MustBeUnique=Must be unique ?
 MustBeMandatory=Must be mandatory to create thirds?
 MustBeInvoiceMandatory=Must be mandatory to validate invoices?
@@ -1199,7 +1199,7 @@ LDAPDescUsers=This page allows you to define LDAP attributes name in LDAP tree f
 LDAPDescGroups=This page allows you to define LDAP attributes name in LDAP tree for each data found on Dolibarr groups.
 LDAPDescMembers=This page allows you to define LDAP attributes name in LDAP tree for each data found on Dolibarr members module.
 LDAPDescValues=Example values are designed for <b>OpenLDAP</b> with following loaded schemas: <b>core.schema, cosine.schema, inetorgperson.schema</b>). If you use thoose values and OpenLDAP, modify your LDAP config file <b>slapd.conf</b> to have all thoose schemas loaded.
-ForANonAnonymousAccess=For an authenticated acces (for a write access for example)
+ForANonAnonymousAccess=For an authenticated access (for a write access for example)
 ##### Products #####
 ProductSetup=Products module setup
 ServiceSetup=Services module setup
@@ -1209,7 +1209,7 @@ ConfirmDeleteProductLineAbility=Confirmation when removing product lines in form
 ModifyProductDescAbility=Personalization of product descriptions in forms
 ViewProductDescInFormAbility=Visualization of product descriptions in the forms (otherwise as popup tooltip)
 ViewProductDescInThirdpartyLanguageAbility=Visualization of products descriptions in the thirdparty language
-UseSearchToSelectProduct=Use a search form to choose a product (instead of using a list box).<br>Also if you have a large number of product (> 100 000), you can increase speed by setting constant PRODUCT_DONOTSEARCH_ANYWHERE to 1 in Setup->Other. Search will then be limited to start of string.
+UseSearchToSelectProduct=Use a search form to choose a product (rather than a drop-down list).<br>Also if you have a large number of product (> 100 000), you can increase speed by setting constant PRODUCT_DONOTSEARCH_ANYWHERE to 1 in Setup->Other. Search will then be limited to start of string.
 UseEcoTaxeAbility=Support Eco-Taxe (WEEE)
 SetDefaultBarcodeTypeProducts=Default barcode type to use for products
 SetDefaultBarcodeTypeThirdParties=Default barcode type to use for third parties
diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang
index 288d769282e48b3f52b5f612c491fada99320e27..d71f04ac698c0462dcebf8e11baf057ec99bc221 100644
--- a/htdocs/langs/fr_FR/admin.lang
+++ b/htdocs/langs/fr_FR/admin.lang
@@ -939,6 +939,7 @@ ExtraFieldsThirdParties=Attributs supplémentaires (tiers)
 ExtraFieldsContacts=Attributs supplémentaires (contacts/adresses)
 ExtraFieldsMember=Attributs supplémentaires (adhérents)
 ExtraFieldsMemberType=Attributs supplémentaires (type d'adhérents)
+ExtraFieldsCustomerInvoices=Attributs supplémentaires (factures clients)
 ExtraFieldHasWrongValue=L'attribut %s a une valeur incorrecte.
 AlphaNumOnlyCharsAndNoSpace=uniquement caractères alphanumériques sans espace
 SendingMailSetup=Configuration de l'envoi par mail
diff --git a/htdocs/mailmanspip/class/mailmanspip.class.php b/htdocs/mailmanspip/class/mailmanspip.class.php
index 845069327b0c4d407c51dde95a75359980ee9b46..9e10c315dfa997b03b4a0c92d244add132b6dcfe 100644
--- a/htdocs/mailmanspip/class/mailmanspip.class.php
+++ b/htdocs/mailmanspip/class/mailmanspip.class.php
@@ -176,7 +176,7 @@ class MailmanSpip
                     require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
                     $mdpass=dol_hash($object->pass);
                     $htpass=crypt($object->pass,makesalt());
-                    $query = "INSERT INTO spip_auteurs (nom, email, login, pass, htpass, alea_futur, statut) VALUES(\"".$object->firstname." ".$object->lastname."\",\"".$object->email."\",\"".$object->login."\",\"$mdpass\",\"$htpass\",FLOOR(32000*RAND()),\"1comite\")";
+                    $query = "INSERT INTO spip_auteurs (nom, email, login, pass, htpass, alea_futur, statut) VALUES(\"".dolGetFirstLastname($object->firstname,$object->lastname)."\",\"".$object->email."\",\"".$object->login."\",\"$mdpass\",\"$htpass\",FLOOR(32000*RAND()),\"1comite\")";
 
                     $result = $mydb->query($query);
 
diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php
index a8b2f307e709d20666bb363bfdef076b83cda50b..ca97aebb849f5fae4390eadf269c56b1bf3d4bbd 100644
--- a/htdocs/main.inc.php
+++ b/htdocs/main.inc.php
@@ -1566,13 +1566,15 @@ function left_menu($menu_array_before, $helppagename='', $moresearchform='', $me
 
 	    //Dolibarr version
 	    $doliurl='http://www.dolibarr.org';
-	    
 	    $appli='Dolibarr';
-	    if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_APPLICATION_TITLE;
-	    
+	    if (! empty($conf->global->MAIN_APPLICATION_TITLE)) { $appli=$conf->global->MAIN_APPLICATION_TITLE; $doliurl=''; }
 	    $appli.=" ".DOL_VERSION;
 	    
-	    print '<div id="blockvmenuhelp" class="blockvmenuhelp"><a class="help" target="_blank" href="'.$doliurl.'">'.$appli.'</a></div>';
+	    print '<div id="blockvmenuhelp" class="blockvmenuhelp">';
+	    if ($doliurl) print '<a class="help" target="_blank" href="'.$doliurl.'">';
+	    print $appli;
+	    if ($doliurlx) print '</a>';
+	    print '</div>';
 	    
 	    print "</div>\n";
 	    print "<!-- End left menu -->\n";
diff --git a/htdocs/public/donations/donateurs_code.php b/htdocs/public/donations/donateurs_code.php
index f354cffe8a1d72c499e5a352abf00204220b525d..972ba6a657d046c136d11fb6c41bfccc5480eb69 100644
--- a/htdocs/public/donations/donateurs_code.php
+++ b/htdocs/public/donations/donateurs_code.php
@@ -81,10 +81,10 @@ if ($resql)
 			$objp = $db->fetch_object($resql);
 
 			$var=!$var;
-			print "<TR $bc[$var]>";
+			print "<tr ".$bc[$var].">";
 			if ($objp->public)
 			{
-				print "<td>".$objp->firstname." ".$objp->lastname." ".$objp->societe."</td>\n";
+				print "<td>".dolGetFirstLastname($objp->firstname, $objp->lastname)." ".$objp->societe."</td>\n";
 			}
 			else
 			{
diff --git a/htdocs/public/members/public_list.php b/htdocs/public/members/public_list.php
index 6f32d9e4715833d584a14587d66b36335f34377c..de4044e3574385c015e36a2fe5e8121f57ad1e70 100644
--- a/htdocs/public/members/public_list.php
+++ b/htdocs/public/members/public_list.php
@@ -140,7 +140,7 @@ if ($result)
 		$objp = $db->fetch_object($result);
 		$var=!$var;
 		print "<tr $bc[$var]>";
-		print '<td><a href="public_card.php?id='.$objp->rowid.'">'.$objp->firstname.' '.$objp->lastname.($objp->societe?' / '.$objp->societe:'').'</a></td>'."\n";
+		print '<td><a href="public_card.php?id='.$objp->rowid.'">'.dolGetFirstLastname($obj->firstname, $obj->lastname).($objp->societe?' / '.$objp->societe:'').'</a></td>'."\n";
 		//print "<td>$objp->naiss</td>\n"; // est-ce nécessaire ??
 		print '<td>'.$objp->email.'</td>'."\n";
 		print '<td>'.$objp->zip.'</td>'."\n";
diff --git a/htdocs/societe/admin/societe_extrafields.php b/htdocs/societe/admin/societe_extrafields.php
index 66957c0314adbc70aa1fe3eb33d7888770295587..4ad507dc468084a522419d3c3628b4945d47d637 100755
--- a/htdocs/societe/admin/societe_extrafields.php
+++ b/htdocs/societe/admin/societe_extrafields.php
@@ -30,6 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
 
 $langs->load("companies");
 $langs->load("admin");
+$langs->load("members");
 
 $extrafields = new ExtraFields($db);
 $form = new Form($db);
diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php
index 2a25314b5d4e228ef52be33e131f1fc86d8924f4..c87a6ef11f411c23e87caee5930b0cdee025cca9 100644
--- a/htdocs/societe/class/societe.class.php
+++ b/htdocs/societe/class/societe.class.php
@@ -1616,7 +1616,7 @@ class Societe extends CommonObject
                     $obj = $this->db->fetch_object($resql);
                     if ($mode == 'email') $property=$obj->email;
                     else if ($mode == 'mobile') $property=$obj->phone_mobile;
-                    $contact_property[$obj->rowid] = trim($obj->firstname." ".$obj->lastname)." &lt;".$property."&gt;";
+                    $contact_property[$obj->rowid] = trim(dolGetFirstLastname($obj->firstname,$obj->lastname))." &lt;".$property."&gt;";
                     $i++;
                 }
             }
@@ -1649,7 +1649,7 @@ class Societe extends CommonObject
                 while ($i < $nump)
                 {
                     $obj = $this->db->fetch_object($resql);
-                    $contacts[$obj->rowid] = $obj->firstname." ".$obj->lastname;
+                    $contacts[$obj->rowid] = dolGetFirstLastname($obj->firstname,$obj->lastname);
                     $i++;
                 }
             }
@@ -1685,7 +1685,7 @@ class Societe extends CommonObject
             {
                 $obj = $this->db->fetch_object($resql);
 
-                if ($mode == 'email') $contact_property = "$obj->firstname $obj->lastname <$obj->email>";
+                if ($mode == 'email') $contact_property = dolGetFirstLastname($obj->firstname, $obj->lastname)." <".$obj->email.">";
                 else if ($mode == 'mobile') $contact_property = $obj->phone_mobile;
             }
             return $contact_property;
diff --git a/htdocs/societe/commerciaux.php b/htdocs/societe/commerciaux.php
index 0fa9f78353b3886f86c804da7ddd0257065c1e7d..a4f1dee5a7b0eb5d2ae62671fbf66806e93b7f74 100644
--- a/htdocs/societe/commerciaux.php
+++ b/htdocs/societe/commerciaux.php
@@ -188,7 +188,7 @@ if ($_GET["socid"])
 
 			print '<a href="'.DOL_URL_ROOT.'/user/fiche.php?id='.$obj->rowid.'">';
 			print img_object($langs->trans("ShowUser"),"user").' ';
-			print $obj->firstname." " .$obj->lastname."\n";
+			print dolGetFirstLastname($obj->firstname, $obj->lastname)."\n";
 			print '</a>&nbsp;';
 			if ($user->rights->societe->creer)
 			{
@@ -254,7 +254,7 @@ if ($_GET["socid"])
 				print "<tr $bc[$var]><td>";
 				print '<a href="'.DOL_URL_ROOT.'/user/fiche.php?id='.$obj->rowid.'">';
 				print img_object($langs->trans("ShowUser"),"user").' ';
-				print $obj->firstname." " .$obj->lastname."\n";
+				print dolGetFirstLastname($obj->firstname, $obj->lastname)."\n";
 				print '</a>';
 				print '</td><td>'.$obj->login.'</td>';
 				print '<td><a href="commerciaux.php?socid='.$_GET["socid"].'&amp;commid='.$obj->rowid.'">'.$langs->trans("Add").'</a></td>';
diff --git a/htdocs/societe/notify/index.php b/htdocs/societe/notify/index.php
index 9a1fc344a53d85ba0d3372d63756836a02e7a129..943d55669bfb3a542174c307b708ecc7fed68f4d 100644
--- a/htdocs/societe/notify/index.php
+++ b/htdocs/societe/notify/index.php
@@ -93,9 +93,9 @@ if ($result)
 
 		$var=!$var;
 
-		print "<tr $bc[$var]>";
-		print "<td><a href=\"fiche.php?socid=".$obj->socid."\">$obj->nom</A></td>\n";
-		print "<td>".$obj->firstname." ".$obj->lastname."</td>\n";
+		print "<tr ".$bc[$var].">";
+		print "<td><a href=\"fiche.php?socid=".$obj->socid."\">".$obj->nom."</a></td>\n";
+		print "<td>".dolGetFirstLastname($obj->firstname, $obj->lastname)."</td>\n";
 		print "<td>".$obj->titre."</td>\n";
 		print "</tr>\n";
 		$i++;
@@ -108,7 +108,7 @@ else
 	dol_print_error($db);
 }
 
-$db->close();
 
 llxFooter();
+$db->close();
 ?>
diff --git a/htdocs/societe/tpl/linesalesrepresentative.tpl.php b/htdocs/societe/tpl/linesalesrepresentative.tpl.php
index 63892395df73af1cc5cabb53e3c970df70533ea0..9b2867cacff02c8b4acbb8f4752a9049f8f8fa71 100644
--- a/htdocs/societe/tpl/linesalesrepresentative.tpl.php
+++ b/htdocs/societe/tpl/linesalesrepresentative.tpl.php
@@ -27,7 +27,7 @@
             foreach($listsalesrepresentatives as $val)
             {
                 $userstatic->id=$val['id'];
-                $userstatic->lastname=$val['name'];
+                $userstatic->lastname=$val['lastname'];
                 $userstatic->firstname=$val['firstname'];
                 print $userstatic->getNomUrl(1);
                 $i++;
diff --git a/htdocs/user/fiche.php b/htdocs/user/fiche.php
index 79e77debffa7befbe599820a94fd6fa7b044f144..5c4ddac97188a7595bd515ef115099c383c3d366 100644
--- a/htdocs/user/fiche.php
+++ b/htdocs/user/fiche.php
@@ -1076,7 +1076,7 @@ else
 
             // Lastname
             print '<tr><td valign="top">'.$langs->trans("Lastname").'</td>';
-            print '<td>'.$object->nom.'</td>';
+            print '<td>'.$object->lastname.'</td>';
 
             // Photo
             print '<td align="center" valign="middle" width="25%" rowspan="'.$rowspan.'">';
diff --git a/scripts/emailings/cron-mailing-send.php b/scripts/emailings/cron-mailing-send.php
index 658d899a677f4721da2bf4417ba20bf2b8e01034..e1290f4f7695c998cd23e6bdd017de735ec68ba0 100644
--- a/scripts/emailings/cron-mailing-send.php
+++ b/scripts/emailings/cron-mailing-send.php
@@ -120,7 +120,7 @@ if ($resql)
 						$obj2 = $db->fetch_object($resql);
 
 						// sendto en RFC2822
-						$sendto = str_replace(',',' ',$obj2->firstname." ".$obj2->lastname) ." <".$obj2->email.">";
+						$sendto = str_replace(',',' ',dolGetFirstLastname($obj2->firstname, $obj2->lastname)) ." <".$obj2->email.">";
 
 						// Make subtsitutions on topic and body
 						$other=explode(';',$obj2->other);
diff --git a/scripts/emailings/mailing-send.php b/scripts/emailings/mailing-send.php
index 953c967bcb2291935cc826ce8bbd5f51e4457855..6db9eb00c2a8a36d7cf46a660af06690810d8d2c 100644
--- a/scripts/emailings/mailing-send.php
+++ b/scripts/emailings/mailing-send.php
@@ -127,7 +127,7 @@ if ($resql)
 			$obj = $db->fetch_object($resql);
 
 			// sendto en RFC2822
-			$sendto = str_replace(',',' ',$obj->firstname." ".$obj->lastname) ." <".$obj->email.">";
+			$sendto = str_replace(',',' ',dolGetFirstLastname($obj->firstname, $obj->lastname) ." <".$obj->email.">";
 
 			// Make subtsitutions on topic and body
 			$other=explode(';',$obj->other);
diff --git a/scripts/invoices/email_unpaid_invoices_to_representatives.php b/scripts/invoices/email_unpaid_invoices_to_representatives.php
index 2d3bd6f6c758f89c65332f3f167719be654da65d..6abb260acf1fac97b84d0e05290ac5ed19a5131e 100755
--- a/scripts/invoices/email_unpaid_invoices_to_representatives.php
+++ b/scripts/invoices/email_unpaid_invoices_to_representatives.php
@@ -2,7 +2,7 @@
 <?php
 /*
  * Copyright (C) 2005      Rodolphe Quiedeville <rodolphe@quiedeville.org>
- * Copyright (C) 2005-2009 Laurent Destailleur  <eldy@users.sourceforge.net>
+ * Copyright (C) 2005-2013 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
@@ -35,67 +35,95 @@ if (substr($sapi_type, 0, 3) == 'cgi') {
     exit;
 }
 
-if (! isset($argv[1]) || ! $argv[1]) {
-	print "Usage: $script_file now\n";
+if (! isset($argv[1]) || ! $argv[1] || ! in_array($argv[1],array('test','confirm'))) 
+{
+	print "Usage: $script_file [test|confirm] [delay]\n";
+	print "\n";
+	print "Send an email to users to remind all unpaid invoices of customers they are sale representative for.\n";
+	print "If you choose 'test' mode, no emails are sent.\n";
+	print "If you add a delay (nb of days), only invoice with due date < today + delay are included.\n";
 	exit;
 }
+$mode=$argv[1];
 
 
 require($path."../../htdocs/master.inc.php");
 require_once (DOL_DOCUMENT_ROOT."/core/class/CMailFile.class.php");
 
 
+/*
+ * Main
+ */
+
+$now=dol_now('tzserver');
+$duration_value=$argv[2];
+
 $error = 0;
+print $script_file." launched with mode ".$mode.($duration_value?" delay=".$duration_value:"")."\n";
 
-$sql = "SELECT f.facnumber, f.total_ttc, s.nom as name, u.lastname, u.firstname, u.email";
+$sql = "SELECT f.facnumber, f.total_ttc, s.nom as name, u.rowid as uid, u.lastname, u.firstname, u.email, u.lang";
 $sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
 $sql .= " , ".MAIN_DB_PREFIX."societe as s";
 $sql .= " , ".MAIN_DB_PREFIX."societe_commerciaux as sc";
 $sql .= " , ".MAIN_DB_PREFIX."user as u";
-$sql .= " WHERE f.paye = 0";
+$sql .= " WHERE f.fk_statut != 0 AND f.paye = 0";
 $sql .= " AND f.fk_soc = s.rowid";
+if ($duration_value) $sql .= " AND f.date_lim_reglement < '".$db->idate(dol_time_plus_duree($now, $duration_value, "d"))."'";
 $sql .= " AND sc.fk_soc = s.rowid";
 $sql .= " AND sc.fk_user = u.rowid";
-$sql .= " ORDER BY u.email ASC, s.rowid ASC";
+$sql .= " ORDER BY u.email ASC, s.rowid ASC";	// Order by email to allow one message per email
 
+//print $sql;
 $resql=$db->query($sql);
 if ($resql)
 {
     $num = $db->num_rows($resql);
     $i = 0;
-    $oldemail = '';
-    $message = '';
-    $total = '';
-    dol_syslog("email_unpaid_invoices_to_representatives.php");
-
+    $oldemail = 'none'; $olduid = 0; $oldlang='';
+    $total = 0;
+	print "We found ".$num." couples (unpayed validated invoice/sale representative) qualified\n";
+    dol_syslog("We found ".$num." couples (unpayed validated invoice/sale representative) qualified");
+	$message='';
+	
     if ($num)
     {
         while ($i < $num)
         {
             $obj = $db->fetch_object($resql);
 
-            if ($obj->email <> $oldemail)
+            if (($obj->email <> $oldemail || $obj->uid <> $olduid) || $oldemail == 'none')
             {
-                if (dol_strlen($oldemail))
+                // Break onto sales representative (new email or uid)
+                if (dol_strlen($oldemail) && $oldemail != 'none')
                 {
-                    envoi_mail($oldemail,$message,$total);
+                   	envoi_mail($mode,$oldemail,$message,$total,$oldlang);
                 }
                 $oldemail = $obj->email;
+                $olduid = $obj->uid;
+                $oldlang = $obj->lang;
                 $message = '';
                 $total = 0;
+                if (empty($obj->email)) print "Warning: Sal representative ".dolGetFirstLastname($obj->firstname, $obj->lastname)." has no email. Notice disabled.\n";
             }
 
-            $message .= $langs->trans("Invoice")." ".$obj->facnumber." : ".price($obj->total_ttc)." : ".$obj->name."\n";
-            $total += $obj->total_ttc;
+            if (dol_strlen($oldemail))
+            {
+            	$message .= $langs->trans("Invoice")." ".$obj->facnumber." : ".price($obj->total_ttc)." : ".$obj->name."\n";
+				print "Invoice ".$obj->facnumber.", price ".price2num($obj->total_ttc).", linked to company ".$obj->name." with sale representative ".dolGetFirstLastname($obj->firstname, $obj->lastname)." qualified.\n";
+            	dol_syslog("email_unpaid_invoices_to_representatives.php: ".$obj->email);
+            }
 
-            dol_syslog("email_unpaid_invoices_to_representatives.php: ".$obj->email);
+            $total += $obj->total_ttc;
             $i++;
         }
 
         // Si il reste des envois en buffer
         if ($total)
         {
-            envoi_mail($oldemail,$message,$total);
+            if (dol_strlen($oldemail) && $oldemail != 'none')	// Break onto email (new email)
+            {
+       			envoi_mail($mode,$oldemail,$message,$total,$oldlang);
+            }
         }
     }
     else
@@ -109,6 +137,7 @@ else
     dol_syslog("email_unpaid_invoices_to_representatives.php: Error");
 }
 
+
 /**
  * 	Send email
  *
@@ -117,25 +146,29 @@ else
  * 	@param	string	$total		Total amount of unpayed invoices
  * 	@return	int					<0 if KO, >0 if OK
  */
-function envoi_mail($oldemail,$message,$total)
+function envoi_mail($mode,$oldemail,$message,$total,$userlang)
 {
     global $conf,$langs;
+    global $db;
 
-    $subject = "[Dolibarr] List of unpaid invoices";
+    $newlangs=new Translate($db,$conf);
+    $newlangs->setDefaultLang($userlang);
+    
+    $subject = "[".($conf->global->MAIN_APPLICATION_TITLE)."] ".$newlangs->trans("ListOfYourUnpaidInvoices");
     $sendto = $oldemail;
     $from = $conf->global->MAIN_EMAIL_FROM;
     $errorsto = $conf->global->MAIN_MAIL_ERRORS_TO;
 	$msgishtml = 0;
 
-    print "Envoi mail pour $oldemail, total: $total\n";
-    dol_syslog("email_unpaid_invoices_to_representatives.php: send mail to $oldemail");
+    print "Send email for ".$oldemail.", total: ".$total."\n";
+    dol_syslog("email_unpaid_invoices_to_representatives.php: send mail to ".$oldemail);
 
     $allmessage = "List of unpaid invoices\n";
-    $allmessage .= "This list contains only invoices for third parties you are linked to as a sales representative.\n";
-    $allmessage .= "\n";
-    $allmessage .= $message;
-    $allmessage .= "\n";
-    $allmessage .= $langs->trans("Total")." = ".price($total)."\n";
+    $allmessage.= "This list contains only invoices for third parties you are linked to as a sales representative.\n";
+    $allmessage.= "\n";
+    $allmessage.= $message;
+    $allmessage.= "\n";
+    $allmessage.= $langs->trans("Total")." = ".price($total)."\n";
 
     $mail = new CMailFile(
         $subject,
@@ -153,7 +186,12 @@ function envoi_mail($oldemail,$message,$total)
 
     $mail->errors_to = $errorsto;
 
-    $result=$mail->sendfile();
+    if ($mode == 'confirm')
+    {
+    	$result=$mail->sendfile();
+    }
+    else $result=1;
+    
     if ($result)
     {
         return 1;