diff --git a/ChangeLog b/ChangeLog
index 55249d9fb826b7d0df97dd59c8bc8c4afbfe38c1..028cc1c85e70ab17360b03bf753154198e1c1e9a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -30,6 +30,9 @@ For users:
 - New: Add option MAIN_GENERATE_DOCUMENT_WITH_PICTURE.
 - New: Add option excludethirdparties and onlythirdparties into merge pdf scripts.
 - Qual: Implement same rule for return value of all command line scripts (0 when success, <>0 if error).
+- New : [ task #925 ] Add ODT document generation for Tasks in project module
+- New : [ task #924 ] Add numbering rule on task
+
 
 For translators:
 - Normalized sort order of all languages files with english reference files.
diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php
index 9290c9873bf319f3b8b0c0762348c2e378bc76b3..78bf317d3a9036940f3fa35753acb3b39456d271 100644
--- a/htdocs/core/class/html.formfile.class.php
+++ b/htdocs/core/class/html.formfile.class.php
@@ -309,6 +309,15 @@ class FormFile
                     $modellist=ModelePDFProjects::liste_modeles($this->db);
                 }
             }
+            elseif ($modulepart == 'project_task')
+            {
+            	if (is_array($genallowed)) $modellist=$genallowed;
+            	else
+            	{
+            		include_once DOL_DOCUMENT_ROOT.'/core/modules/project/task/modules_task.php';
+            		$modellist=ModelePDFTask::liste_modeles($this->db);
+            	}
+            }
             elseif ($modulepart == 'export')
             {
                 if (is_array($genallowed)) $modellist=$genallowed;
diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php
index e5ea867d0a7b2990792e5ae364ca50a08e737821..52978d6534958726a74eccb78a9d5743d4633ac3 100644
--- a/htdocs/core/lib/project.lib.php
+++ b/htdocs/core/lib/project.lib.php
@@ -281,12 +281,12 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
 				print '<td>';
 				if ($showlineingray)
 				{
-					print '<i>'.img_object('','projecttask').' '.$lines[$i]->id.'</i>';
+					print '<i>'.img_object('','projecttask').' '.$lines[$i]->ref.'</i>';
 				}
 				else
 				{
 					$taskstatic->id=$lines[$i]->id;
-					$taskstatic->ref=$lines[$i]->id;
+					$taskstatic->ref=$lines[$i]->ref;
 					$taskstatic->label=($taskrole[$lines[$i]->id]?$langs->trans("YourRole").': '.$taskrole[$lines[$i]->id]:'');
 					print $taskstatic->getNomUrl(1,($showproject?'':'withproject'));
 				}
diff --git a/htdocs/core/modules/modProjet.class.php b/htdocs/core/modules/modProjet.class.php
index e5f956b09460406ab05ec4fbde0c0d0918967d2a..7b9ec52aef68325c3d16532291fd6da071ca0796 100644
--- a/htdocs/core/modules/modProjet.class.php
+++ b/htdocs/core/modules/modProjet.class.php
@@ -4,6 +4,7 @@
  * Copyright (C) 2004      Sebastien Di Cintio  <sdicintio@ressource-toi.org>
  * Copyright (C) 2004      Benoit Mortier       <benoit.mortier@opensides.be>
  * Copyright (C) 2005-2012 Regis Houssin        <regis.houssin@capnetworks.com>
+ * Copyright (C) 2013	   Florian Henry        <florian.henry@open-concept.pro>
  *
  * 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
@@ -75,14 +76,14 @@ class modProjet extends DolibarrModules
 		$this->const[$r][0] = "PROJECT_ADDON_PDF";
 		$this->const[$r][1] = "chaine";
 		$this->const[$r][2] = "baleine";
-		$this->const[$r][3] = 'Nom du gestionnaire de generation des projets en PDF';
+		$this->const[$r][3] = 'Name of PDF/ODT project manager class';
 		$this->const[$r][4] = 0;
 		$r++;
 
 		$this->const[$r][0] = "PROJECT_ADDON";
 		$this->const[$r][1] = "chaine";
 		$this->const[$r][2] = "mod_project_simple";
-		$this->const[$r][3] = 'Nom du gestionnaire de numerotation des projets';
+		$this->const[$r][3] = 'Name of Numbering Rule project manager class';
 		$this->const[$r][4] = 0;
 		$r++;
 
@@ -92,6 +93,27 @@ class modProjet extends DolibarrModules
 		$this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/projects";
 		$this->const[$r][3] = "";
 		$this->const[$r][4] = 0;
+		
+		$this->const[$r][0] = "PROJECT_TASK_ADDON_PDF";
+		$this->const[$r][1] = "chaine";
+		$this->const[$r][2] = "";
+		$this->const[$r][3] = 'Name of PDF/ODT tasks manager class';
+		$this->const[$r][4] = 0;
+		$r++;
+		
+		$this->const[$r][0] = "PROJECT_TASK_ADDON";
+		$this->const[$r][1] = "chaine";
+		$this->const[$r][2] = "mod_task_simple";
+		$this->const[$r][3] = 'Name of Numbering Rule task manager class';
+		$this->const[$r][4] = 0;
+		$r++;
+		
+		$r++;
+		$this->const[$r][0] = "PROJECT_TASK_ADDON_PDF_ODT_PATH";
+		$this->const[$r][1] = "chaine";
+		$this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/tasks";
+		$this->const[$r][3] = "";
+		$this->const[$r][4] = 0;
 
 		// Boxes
 		$this->boxes = array();
diff --git a/htdocs/core/modules/project/task/mod_task_simple.php b/htdocs/core/modules/project/task/mod_task_simple.php
new file mode 100644
index 0000000000000000000000000000000000000000..25cc347bcf94345ae78659679de92de4b2f5587d
--- /dev/null
+++ b/htdocs/core/modules/project/task/mod_task_simple.php
@@ -0,0 +1,152 @@
+<?php
+/* Copyright (C) 2010-2012	Regis Houssin		<regis.houssin@capnetworks.com>
+ * Copyright (C) 2010		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/>.
+ * or see http://www.gnu.org/
+ */
+
+/**
+ *	\file       htdocs/core/modules/project/mod_project_simple.php
+ *	\ingroup    project
+ *	\brief      File with class to manage the numbering module Simple for project references
+ */
+
+require_once DOL_DOCUMENT_ROOT .'/core/modules/project/task/modules_task.php';
+
+
+/**
+ * 	Class to manage the numbering module Simple for project references
+ */
+class mod_task_simple extends ModeleNumRefTask
+{
+	var $version='dolibarr';		// 'development', 'experimental', 'dolibarr'
+	var $prefix='TK';
+    var $error='';
+	var $nom = "Simple";
+
+
+    /** 
+     *  Return description of numbering module
+     * 
+     *  @return     string      Text with description
+     */
+    function info()
+    {
+    	global $langs;
+      	return $langs->trans("SimpleNumRefModelDesc",$this->prefix);
+    }
+
+
+    /** 
+     *  Return an example of numbering module values
+     * 
+     * 	@return     string      Example
+     */
+    function getExample()
+    {
+        return $this->prefix."0501-0001";
+    }
+
+
+    /**  Test si les numeros deja en vigueur dans la base ne provoquent pas de
+     *   de conflits qui empechera cette numerotation de fonctionner.
+     * 
+     *   @return     boolean     false si conflit, true si ok
+     */
+    function canBeActivated()
+    {
+    	global $conf,$langs;
+
+        $coyymm=''; $max='';
+
+		$posindice=8;
+		$sql = "SELECT MAX(SUBSTRING(ref FROM ".$posindice.")) as max";
+        $sql.= " FROM ".MAIN_DB_PREFIX."projet_task";
+		$sql.= " WHERE ref LIKE '".$this->prefix."____-%'";
+        $sql.= " AND entity = ".$conf->entity;
+        $resql=$db->query($sql);
+        if ($resql)
+        {
+            $row = $db->fetch_row($resql);
+            if ($row) { $coyymm = substr($row[0],0,6); $max=$row[0]; }
+        }
+        if (! $coyymm || preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i',$coyymm))
+        {
+            return true;
+        }
+        else
+        {
+			$langs->load("errors");
+			$this->error=$langs->trans('ErrorNumRefModel',$max);
+            return false;
+        }
+    }
+
+
+   /**
+	*  Return next value
+	* 
+	*  @param   Societe	$objsoc		Object third party
+	*  @param   Task	$Task		Object Task
+	*  @return	string				Value if OK, 0 if KO
+	*/
+    function getNextValue($objsoc,$task)
+    {
+		global $db,$conf;
+
+		// D'abord on recupere la valeur max
+		$posindice=8;
+		$sql = "SELECT MAX(SUBSTRING(ref FROM ".$posindice.")) as max";
+		$sql.= " FROM ".MAIN_DB_PREFIX."projet_task";
+		$sql.= " WHERE ref like '".$this->prefix."____-%'";
+
+		$resql=$db->query($sql);
+		if ($resql)
+		{
+			$obj = $db->fetch_object($resql);
+			if ($obj) $max = intval($obj->max);
+			else $max=0;
+		}
+		else
+		{
+			dol_syslog("mod_task_simple::getNextValue sql=".$sql);
+			return -1;
+		}
+
+		$date=empty($task->date_c)?dol_now():$task->date_c;
+
+		//$yymm = strftime("%y%m",time());
+		$yymm = strftime("%y%m",$date);
+		$num = sprintf("%04s",$max+1);
+
+		dol_syslog("mod_task_simple::getNextValue return ".$this->prefix.$yymm."-".$num);
+		return $this->prefix.$yymm."-".$num;
+    }
+
+
+    /** 
+     * 	Return next reference not yet used as a reference
+     * 
+     *  @param	Societe	$objsoc     Object third party
+     *  @param  Task	$task		Object task
+     *  @return string      		Next not used reference
+     */
+    function task_get_num($objsoc=0,$task='')
+    {
+        return $this->getNextValue($objsoc,$task);
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/htdocs/core/modules/project/task/mod_task_universal.php b/htdocs/core/modules/project/task/mod_task_universal.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e660bd9cdb4f56e38de8c81b8042fb0e78ce268
--- /dev/null
+++ b/htdocs/core/modules/project/task/mod_task_universal.php
@@ -0,0 +1,142 @@
+<?php
+/* Copyright (C) 2010 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/>.
+ * or see http://www.gnu.org/
+ */
+
+/**
+ *	\file       htdocs/core/modules/project/mod_project_universal.php
+ *	\ingroup    project
+ *	\brief      Fichier contenant la classe du modele de numerotation de reference de projet Universal
+ */
+
+require_once DOL_DOCUMENT_ROOT .'/core/modules/project/task/modules_task.php';
+
+
+/**
+ * 	Classe du modele de numerotation de reference de projet Universal
+ */
+class mod_task_universal extends ModeleNumRefTask
+{
+	var $version='dolibarr';		// 'development', 'experimental', 'dolibarr'
+	var $error = '';
+	var $nom = 'Universal';
+
+
+    /**
+     *  Renvoi la description du modele de numerotation
+     * 
+     *  @return     string      Texte descripif
+     */
+	function info()
+    {
+    	global $conf,$langs;
+
+		$langs->load("projects");
+		$langs->load("admin");
+
+		$form = new Form($this->db);
+
+		$texte = $langs->trans('GenericNumRefModelDesc')."<br>\n";
+		$texte.= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
+		$texte.= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+		$texte.= '<input type="hidden" name="action" value="updateMaskTask">';
+		$texte.= '<input type="hidden" name="maskconsttask" value="PROJECT_TASK_UNIVERSAL_MASK">';
+		$texte.= '<table class="nobordernopadding" width="100%">';
+
+		$tooltip=$langs->trans("GenericMaskCodes",$langs->transnoentities("Task"),$langs->transnoentities("Task"));
+		$tooltip.=$langs->trans("GenericMaskCodes2");
+		$tooltip.=$langs->trans("GenericMaskCodes3");
+		$tooltip.=$langs->trans("GenericMaskCodes4a",$langs->transnoentities("Task"),$langs->transnoentities("Task"));
+		$tooltip.=$langs->trans("GenericMaskCodes5");
+
+		// Parametrage du prefix
+		$texte.= '<tr><td>'.$langs->trans("Mask").':</td>';
+		$texte.= '<td align="right">'.$form->textwithpicto('<input type="text" class="flat" size="24" name="masktask" value="'.$conf->global->PROJECT_TASK_UNIVERSAL_MASK.'">',$tooltip,1,1).'</td>';
+
+		$texte.= '<td align="left" rowspan="2">&nbsp; <input type="submit" class="button" value="'.$langs->trans("Modify").'" name="Button"></td>';
+
+		$texte.= '</tr>';
+
+		$texte.= '</table>';
+		$texte.= '</form>';
+
+		return $texte;
+    }
+
+    /**
+     *  Renvoi un exemple de numerotation
+     * 
+     *  @return     string      Example
+     */
+    function getExample()
+    {
+    	global $conf,$langs,$mysoc;
+
+    	$old_code_client=$mysoc->code_client;
+    	$mysoc->code_client='CCCCCCCCCC';
+    	$numExample = $this->getNextValue($mysoc,'');
+		$mysoc->code_client=$old_code_client;
+
+		if (! $numExample)
+		{
+			$numExample = $langs->trans('NotConfigured');
+		}
+		return $numExample;
+    }
+
+   /**
+	*  Return next value
+	* 
+	*  @param	Societe		$objsoc		Object third party
+	*  @param   Project		$project	Object project
+	*  @return  string					Value if OK, 0 if KO
+	*/
+    function getNextValue($objsoc,$project)
+    {
+		global $db,$conf;
+
+		require_once DOL_DOCUMENT_ROOT .'/core/lib/functions2.lib.php';
+
+		// On defini critere recherche compteur
+		$mask=$conf->global->PROJECT_TASK_UNIVERSAL_MASK;
+
+		if (! $mask)
+		{
+			$this->error='NotConfigured';
+			return 0;
+		}
+
+		$date=empty($project->date_c)?dol_now():$project->date_c;
+		$numFinal=get_next_value($db,$mask,'projet_task','ref','',$objsoc->code_client,$date);
+
+		return  $numFinal;
+	}
+
+
+    /**   
+     *  Return next reference not yet used as a reference
+     * 
+     *  @param	Societe		$objsoc     Object third party
+     *  @param  Project		$project	Object project
+     *  @return string      			Next not used reference
+     */
+    function project_get_num($objsoc=0,$project='')
+    {
+        return $this->getNextValue($objsoc,$project);
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/htdocs/core/modules/project/task/modules_task.php b/htdocs/core/modules/project/task/modules_task.php
new file mode 100644
index 0000000000000000000000000000000000000000..824c5d12152ae4d653850060c7e5b0a6d3e54838
--- /dev/null
+++ b/htdocs/core/modules/project/task/modules_task.php
@@ -0,0 +1,252 @@
+<?php
+/* Copyright (C) 2010 Regis Houssin  <regis.houssin@capnetworks.com>
+ * Copyright (C) 2010 Florian Henry  <florian.henry<àopen-concept.pro>
+ *
+ * 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/>.
+ * or see http://www.gnu.org/
+ */
+
+/**
+ *		\file       htdocs/core/modules/project/task/modules_task.php
+ *      \ingroup    project
+ *      \brief      File that contain parent class for task models
+ *                  and parent class for task numbering models
+ */
+require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php';
+
+
+/**
+ *	Parent class for projects models
+ */
+abstract class ModelePDFTask extends CommonDocGenerator
+{
+	var $error='';
+
+
+	/**
+	 *  Return list of active generation modules
+	 *
+     *  @param	DoliDB	$db     			Database handler
+     *  @param  string	$maxfilenamelength  Max length of value to show
+     *  @return	array						List of templates
+	 */
+	static function liste_modeles($db,$maxfilenamelength=0)
+	{
+		global $conf;
+
+		$type='project_task';
+		$liste=array();
+
+		include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+		$liste=getListOfModels($db,$type,$maxfilenamelength);
+
+		return $liste;
+	}
+}
+
+
+
+/**
+ *  Classe mere des modeles de numerotation des references de projets
+ */
+abstract class ModeleNumRefTask
+{
+	var $error='';
+
+	/**
+	 *  Return if a module can be used or not
+	 *
+	 *  @return		boolean     true if module can be used
+	 */
+	function isEnabled()
+	{
+		return true;
+	}
+
+	/**
+	 *  Renvoi la description par defaut du modele de numerotation
+	 *
+	 *  @return     string      Texte descripif
+	 */
+	function info()
+	{
+		global $langs;
+		$langs->load("projects");
+		return $langs->trans("NoDescription");
+	}
+
+	/**
+	 *  Renvoi un exemple de numerotation
+	 *
+	 *  @return     string      Example
+	 */
+	function getExample()
+	{
+		global $langs;
+		$langs->load("projects");
+		return $langs->trans("NoExample");
+	}
+
+	/**
+	 *  Test si les numeros deja en vigueur dans la base ne provoquent pas de
+	 *  de conflits qui empechera cette numerotation de fonctionner.
+	 *
+	 *  @return     boolean     false si conflit, true si ok
+	 */
+	function canBeActivated()
+	{
+		return true;
+	}
+
+	/**
+	 *  Renvoi prochaine valeur attribuee
+	 *	
+	 *	@param	Societe		$objsoc		Object third party
+	 *	@param	Project		$project	Object project
+	 *	@return	string					Valeur
+	 */
+	function getNextValue($objsoc, $project)
+	{
+		global $langs;
+		return $langs->trans("NotAvailable");
+	}
+
+	/**
+	 *  Renvoi version du module numerotation
+	 *
+	 *  @return     string      Valeur
+	 */
+	function getVersion()
+	{
+		global $langs;
+		$langs->load("admin");
+
+		if ($this->version == 'development') return $langs->trans("VersionDevelopment");
+		if ($this->version == 'experimental') return $langs->trans("VersionExperimental");
+		if ($this->version == 'dolibarr') return DOL_VERSION;
+		return $langs->trans("NotAvailable");
+	}
+}
+
+
+/**
+ *  Create an intervention document on disk using template defined into PROJECT_TASK_ADDON_PDF
+ *
+ *  @param	DoliDB		$db  			objet base de donnee
+ *  @param	Object		$object			Object fichinter
+ *  @param	string		$modele			force le modele a utiliser ('' par defaut)
+ *  @param	Translate	$outputlangs	objet lang a utiliser pour traduction
+ *  @param  int			$hidedetails    Hide details of lines
+ *  @param  int			$hidedesc       Hide description
+ *  @param  int			$hideref        Hide ref
+ *  @param  HookManager	$hookmanager	Hook manager instance
+ *  @return int         				0 if KO, 1 if OK
+ */
+function task_pdf_create($db, $object, $modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $hookmanager=false)
+{
+	global $conf,$langs;
+	$langs->load("projects");
+
+	$error=0;
+
+	$srctemplatepath='';
+
+	// Positionne modele sur le nom du modele de projet a utiliser
+	if (! dol_strlen($modele))
+	{
+		if (! empty($conf->global->PROJECT_TASK_ADDON_PDF))
+		{
+			$modele = $conf->global->PROJECT_TASK_ADDON_PDF;
+		}
+		else
+		{
+			$modele='baleine';
+		}
+	}
+
+	// If selected modele is a filename template (then $modele="modelname:filename")
+	$tmp=explode(':',$modele,2);
+    if (! empty($tmp[1]))
+    {
+        $modele=$tmp[0];
+        $srctemplatepath=$tmp[1];
+    }
+
+	// Search template files
+	$file=''; $classname=''; $filefound=0;
+	$dirmodels=array('/');
+	if (is_array($conf->modules_parts['models'])) $dirmodels=array_merge($dirmodels,$conf->modules_parts['models']);
+	foreach($dirmodels as $reldir)
+	{
+    	foreach(array('doc','pdf') as $prefix)
+    	{
+    	    $file = $prefix."_".$modele.".modules.php";
+
+    		// On verifie l'emplacement du modele
+	        $file=dol_buildpath($reldir."core/modules/project/task/pdf/".$file,0);
+    		if (file_exists($file))
+    		{
+    			$filefound=1;
+    			$classname=$prefix.'_'.$modele;
+    			break;
+    		}
+    	}
+    	if ($filefound) break;
+    }
+
+	// Charge le modele
+	if ($filefound)
+	{
+		require_once $file;
+
+		$obj = new $classname($db);
+		
+		// We save charset_output to restore it because write_file can change it if needed for
+		// output format that does not support UTF8.
+		$sav_charset_output=$outputlangs->charset_output;
+		if ($obj->write_file($object, $outputlangs, $srctemplatepath, $hidedetails, $hidedesc, $hideref, $hookmanager) > 0)
+		{
+			$outputlangs->charset_output=$sav_charset_output;
+
+			// we delete preview files
+        	require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+			dol_delete_preview($object);
+
+			// Success in building document. We build meta file.
+			dol_meta_create($object);
+
+			// Appel des triggers
+			/*include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
+			$interface=new Interfaces($db);
+			$result=$interface->run_triggers('PROJECT_BUILDDOC',$object,$user,$langs,$conf);
+			if ($result < 0) { $error++; $this->errors=$interface->errors; }*/
+			// Fin appel triggers
+
+			return 1;
+		}
+		else
+		{
+			$outputlangs->charset_output=$sav_charset_output;
+			dol_print_error($db,"task_pdf_create Error: ".$obj->error);
+			return 0;
+		}
+	}
+	else
+	{
+		print $langs->trans("Error")." ".$langs->trans("ErrorFileDoesNotExists",$file);
+		return 0;
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/htdocs/core/modules/project/task/pdf/doc_generic_task_odt.modules.php b/htdocs/core/modules/project/task/pdf/doc_generic_task_odt.modules.php
new file mode 100644
index 0000000000000000000000000000000000000000..3a9c86bdb09c61c6c536e8367d95e7508fc6ca06
--- /dev/null
+++ b/htdocs/core/modules/project/task/pdf/doc_generic_task_odt.modules.php
@@ -0,0 +1,844 @@
+<?php
+/* Copyright (C) 2010-2012 	Laurent Destailleur <eldy@users.sourceforge.net>
+ * Copyright (C) 2012		Juanjo Menent		<jmenent@2byte.es>
+* Copyright (C) 2013		Florian Henry		<florian.henry@ope-concept.pro>
+*
+* 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/>.
+* or see http://www.gnu.org/
+*/
+
+/**
+ *	\file       htdocs/core/modules/project/task/pdf/doc_generic_task_odt.modules.php
+ *	\ingroup    project
+ *	\brief      File of class to build ODT documents for third parties
+*/
+
+require_once DOL_DOCUMENT_ROOT.'/core/modules/project/modules_project.php';
+require_once DOL_DOCUMENT_ROOT.'/core/modules/project/task/modules_task.php';
+require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
+require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
+require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
+require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
+require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
+if (! empty($conf->propal->enabled))      require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
+if (! empty($conf->facture->enabled))     require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
+if (! empty($conf->facture->enabled))     require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
+if (! empty($conf->commande->enabled))    require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
+if (! empty($conf->fournisseur->enabled)) require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
+if (! empty($conf->fournisseur->enabled)) require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
+if (! empty($conf->contrat->enabled))     require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
+if (! empty($conf->ficheinter->enabled))  require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
+if (! empty($conf->deplacement->enabled)) require_once DOL_DOCUMENT_ROOT.'/compta/deplacement/class/deplacement.class.php';
+if (! empty($conf->agenda->enabled))      require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
+
+
+/**
+ *	Class to build documents using ODF templates generator
+ */
+class doc_generic_task_odt extends ModelePDFTask
+{
+	var $emetteur;	// Objet societe qui emet
+
+	var $phpmin = array(5,2,0);	// Minimum version of PHP required by module
+	var $version = 'dolibarr';
+
+
+	/**
+	 *	Constructor
+	 *
+	 *  @param		DoliDB		$db      Database handler
+	 */
+	function __construct($db)
+	{
+		global $conf,$langs,$mysoc;
+
+		$langs->load("main");
+		$langs->load("companies");
+
+		$this->db = $db;
+		$this->name = "ODT templates";
+		$this->description = $langs->trans("DocumentModelOdt");
+		$this->scandir = 'PROJECT_TASK_ADDON_PDF_ODT_PATH';	// Name of constant that is used to save list of directories to scan
+
+		// Dimension page pour format A4
+		$this->type = 'odt';
+		$this->page_largeur = 0;
+		$this->page_hauteur = 0;
+		$this->format = array($this->page_largeur,$this->page_hauteur);
+		$this->marge_gauche=0;
+		$this->marge_droite=0;
+		$this->marge_haute=0;
+		$this->marge_basse=0;
+
+		$this->option_logo = 1;                    // Affiche logo
+		$this->option_tva = 0;                     // Gere option tva COMMANDE_TVAOPTION
+		$this->option_modereg = 0;                 // Affiche mode reglement
+		$this->option_condreg = 0;                 // Affiche conditions reglement
+		$this->option_codeproduitservice = 0;      // Affiche code produit-service
+		$this->option_multilang = 0;               // Dispo en plusieurs langues
+		$this->option_escompte = 0;                // Affiche si il y a eu escompte
+		$this->option_credit_note = 0;             // Support credit notes
+		$this->option_freetext = 1;				   // Support add of a personalised text
+		$this->option_draft_watermark = 0;		   // Support add of a watermark on drafts
+
+		// Recupere emetteur
+		$this->emetteur=$mysoc;
+		if (! $this->emetteur->pays_code) $this->emetteur->pays_code=substr($langs->defaultlang,-2);    // Par defaut, si n'etait pas defini
+	}
+
+
+	/**
+	 * 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;
+
+		return array(
+		'object_id'=>$object->id,
+		'object_ref'=>$object->ref,
+		'object_title'=>$object->title,
+		'object_description'=>$object->description,
+		'object_date_creation'=>dol_print_date($object->date_c,'day'),
+		'object_date_modification'=>dol_print_date($object->date_m,'day'),
+		'object_date_start'=>dol_print_date($object->date_start,'day'),
+		'object_date_end'=>dol_print_date($object->date_end,'day'),
+		'object_note_private'=>$object->note_private,
+		'object_note_public'=>$object->note_public,
+		'object_public'=>$object->public,
+		'object_statut'=>$object->getLibStatut()
+		);
+	}
+
+	/**
+	 *	Define array with couple substitution key => substitution value
+	 *
+	 *	@param  array			$task				Task Object
+	 *	@param  Translate		$outputlangs        Lang object to use for output
+	 *  @return	array								Return a substitution array
+	 */
+	function get_substitutionarray_tasks($task,$outputlangs)
+	{
+		global $conf;
+
+		return array(
+		'task_ref'=>$task->ref,
+		'task_fk_project'=>$task->fk_project,
+		'task_projectref'=>$task->projectref,
+		'task_projectlabel'=>$task->projectlabel,
+		'task_label'=>$task->label,
+		'task_description'=>$task->description,
+		'task_fk_parent'=>$task->fk_parent,
+		'task_duration'=>$task->duration,
+		'task_progress'=>$task->progress,
+		'task_public'=>$task->public,
+		'task_date_start'=>dol_print_date($task->date_start,'day'),
+		'task_date_end'=>dol_print_date($task->date_end,'day'),
+		'task_note_private'=>$task->note_private,
+		'task_note_public'=>$task->note_public
+		);
+	}
+
+	/**
+	 *	Define array with couple substitution key => substitution value
+	 *
+	 *	@param  array			$contact			Contact array
+	 *	@param  Translate		$outputlangs        Lang object to use for output
+	 *  @return	array								Return a substitution array
+	 */
+	function get_substitutionarray_project_contacts($contact,$outputlangs)
+	{
+		global $conf;
+
+		return array(
+		'projcontacts_id'=>$contact['id'],
+		'projcontacts_rowid'=>$contact['rowid'],
+		'projcontacts_role'=>$contact['libelle'],
+		'projcontacts_lastname'=>$contact['lastname'],
+		'projcontacts_firstname'=>$contact['firstname'],
+		'projcontacts_fullcivname'=>$contact['fullname'],
+		'projcontacts_socname'=>$contact['socname'],
+		'projcontacts_email'=>$contact['email']
+		);
+	}
+
+	/**
+	 *	Define array with couple substitution key => substitution value
+	 *
+	 *	@param  array			$file				file array
+	 *	@param  Translate		$outputlangs        Lang object to use for output
+	 *  @return	array								Return a substitution array
+	 */
+	function get_substitutionarray_project_file($file,$outputlangs)
+	{
+		global $conf;
+
+		return array(
+		'projfile_name'=>$file['name'],
+		'projfile_date'=>dol_print_date($file['date'],'day'),
+		'projfile_size'=>$file['size']
+		);
+	}
+
+	/**
+	 *	Define array with couple substitution key => substitution value
+	 *
+	 *	@param  array			$refdetail			Reference array
+	 *	@param  Translate		$outputlangs        Lang object to use for output
+	 *  @return	array								Return a substitution array
+	 */
+	function get_substitutionarray_project_reference($refdetail,$outputlangs)
+	{
+		global $conf;
+
+		return array(
+		'projref_type'=>$refdetail['type'],
+		'projref_ref'=>$refdetail['ref'],
+		'projref_date'=>dol_print_date($refdetail['date'],'day'),
+		'projref_socname'=>$refdetail['socname'],
+		'projref_amountht'=>price($refdetail['amountht'],0,$outputlangs),
+		'projref_amountttc'=>price($refdetail['amountttc'],0,$outputlangs),
+		'projref_status'=>$refdetail['status']
+		);
+	}
+
+	/**
+	 *	Define array with couple substitution key => substitution value
+	 *
+	 *	@param  array			$taskressource			Reference array
+	 *	@param  Translate		$outputlangs        Lang object to use for output
+	 *  @return	array								Return a substitution array
+	 */
+	function get_substitutionarray_tasksressource($taskressource,$outputlangs)
+	{
+		global $conf;
+		//dol_syslog(get_class($this).'::get_substitutionarray_tasksressource taskressource='.var_export($taskressource,true),LOG_DEBUG);
+		return array(
+		'taskressource_rowid'=>$taskressource['rowid'],
+		'taskressource_role'=>$taskressource['libelle'],
+		'taskressource_lastname'=>$taskressource['lastname'],
+		'taskressource_firstname'=>$taskressource['firstname'],
+		'taskressource_fullcivname'=>$taskressource['fullname'],
+		'taskressource_socname'=>$taskressource['socname'],
+		'taskressource_email'=>$taskressource['email']
+		);
+	}
+
+	/**
+	 *	Define array with couple substitution key => substitution value
+	 *
+	 *	@param  object			$tasktime			times object
+	 *	@param  Translate		$outputlangs        Lang object to use for output
+	 *  @return	array								Return a substitution array
+	 */
+	function get_substitutionarray_taskstime($tasktime,$outputlangs)
+	{
+		global $conf;
+
+		return array(
+		'tasktime_rowid'=>$tasktime['rowid'],
+		'tasktime_task_date'=>dol_print_date($tasktime['task_date'],'day'),
+		'tasktime_task_duration'=>convertSecondToTime($tasktime['task_duration'],'all'),
+		'tasktime_note'=>$tasktime['note'],
+		'tasktime_fk_user'=>$tasktime['fk_user'],
+		'tasktime_user_name'=>$tasktime['name'],
+		'tasktime_user_first'=>$tasktime['firstname'],
+		'tasktime_fullcivname'=>$tasktime['fullcivname']
+		);
+	}
+
+	/**
+	 *	Define array with couple substitution key => substitution value
+	 *
+	 *	@param  array			$file				file array
+	 *	@param  Translate		$outputlangs        Lang object to use for output
+	 *  @return	array								Return a substitution array
+	 */
+	function get_substitutionarray_task_file($file,$outputlangs)
+	{
+		global $conf;
+
+		return array(
+		'tasksfile_name'=>$file['name'],
+		'tasksfile_date'=>dol_print_date($file['date'],'day'),
+		'tasksfile_size'=>$file['size']
+		);
+	}
+
+
+	/**
+	 *	Return description of a module
+	 *
+	 *	@param	Translate	$langs      Lang object to use for output
+	 *	@return string       			Description
+	 */
+	function info($langs)
+	{
+		global $conf,$langs;
+
+		$langs->load("companies");
+		$langs->load("errors");
+
+		$form = new Form($this->db);
+
+		$texte = $this->description.".<br>\n";
+		$texte.= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
+		$texte.= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+		$texte.= '<input type="hidden" name="action" value="setModuleOptionsTask">';
+		$texte.= '<input type="hidden" name="param1" value="PROJECT_TASK_ADDON_PDF_ODT_PATH">';
+		$texte.= '<table class="nobordernopadding" width="100%">';
+
+		// List of directories area
+		$texte.= '<tr><td>';
+		$texttitle=$langs->trans("ListOfDirectories");
+		$listofdir=explode(',',preg_replace('/[\r\n]+/',',',trim($conf->global->PROJECT_TASK_ADDON_PDF_ODT_PATH)));
+		$listoffiles=array();
+		foreach($listofdir as $key=>$tmpdir)
+		{
+			$tmpdir=trim($tmpdir);
+			$tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir);
+			if (! $tmpdir) {
+				unset($listofdir[$key]); continue;
+			}
+			if (! is_dir($tmpdir)) $texttitle.=img_warning($langs->trans("ErrorDirNotFound",$tmpdir),0);
+			else
+			{
+				$tmpfiles=dol_dir_list($tmpdir,'files',0,'\.odt');
+				if (count($tmpfiles)) $listoffiles=array_merge($listoffiles,$tmpfiles);
+			}
+		}
+		$texthelp=$langs->trans("ListOfDirectoriesForModelGenODT");
+		// Add list of substitution keys
+		$texthelp.='<br>'.$langs->trans("FollowingSubstitutionKeysCanBeUsed").'<br>';
+		$texthelp.=$langs->transnoentitiesnoconv("FullListOnOnlineDocumentation");    // This contains an url, we don't modify it
+
+		$texte.= $form->textwithpicto($texttitle,$texthelp,1,'help','',1);
+		$texte.= '<table><tr><td>';
+		$texte.= '<textarea class="flat" cols="60" name="value1">';
+		$texte.=$conf->global->PROJECT_TASK_ADDON_PDF_ODT_PATH;
+		$texte.= '</textarea>';
+		$texte.= '</td>';
+		$texte.= '<td align="center">&nbsp; ';
+		$texte.= '<input type="submit" class="button" value="'.$langs->trans("Modify").'" name="Button">';
+		$texte.= '</td>';
+		$texte.= '</tr>';
+		$texte.= '</table>';
+
+		// Scan directories
+		if (count($listofdir)) $texte.=$langs->trans("NumberOfModelFilesFound").': <b>'.count($listoffiles).'</b>';
+
+		$texte.= '</td>';
+
+
+		$texte.= '<td valign="top" rowspan="2">';
+		$texte.= $langs->trans("ExampleOfDirectoriesForModelGen");
+		$texte.= '</td>';
+		$texte.= '</tr>';
+
+		/*$texte.= '<tr>';
+		 $texte.= '<td align="center">';
+		$texte.= '<input type="submit" class="button" value="'.$langs->trans("Modify").'" name="Button">';
+		$texte.= '</td>';
+		$texte.= '</tr>';*/
+
+		$texte.= '</table>';
+		$texte.= '</form>';
+
+		return $texte;
+	}
+
+	/**
+	 *	Function to build a document on disk using the generic odt module.
+	 *
+	 *	@param	Commande	$object					Object source to build document
+	 *	@param	Translate	$outputlangs			Lang output object
+	 * 	@param	string		$srctemplatepath	    Full path of source filename for generator using a template file
+	 *	@return	int         						1 if OK, <=0 if KO
+	 */
+	function write_file($object,$outputlangs,$srctemplatepath)
+	{
+		global $user,$langs,$conf,$mysoc;
+
+		if (empty($srctemplatepath))
+		{
+			dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING);
+			return -1;
+		}
+
+		if (! is_object($outputlangs)) $outputlangs=$langs;
+		$sav_charset_output=$outputlangs->charset_output;
+		$outputlangs->charset_output='UTF-8';
+
+		$outputlangs->load("main");
+		$outputlangs->load("dict");
+		$outputlangs->load("companies");
+		$outputlangs->load("projects");
+
+		if ($conf->projet->dir_output)
+		{
+			// If $object is id instead of object
+			if (! is_object($object))
+			{
+				$id = $object;
+				$object = new Task($this->db);
+				$result=$object->fetch($id);
+				if ($result < 0)
+				{
+					dol_print_error($this->db,$object->error);
+					return -1;
+				}
+			}
+			$project= new Project($this->db);
+			$project->fetch($object->fk_project);
+
+			$dir = $conf->projet->dir_output. "/" . $project->ref. "/";;
+			$objectref = dol_sanitizeFileName($object->ref);
+			if (! preg_match('/specimen/i',$objectref)) $dir.= "/" . $objectref;
+			$file = $dir . "/" . $objectref . ".odt";
+
+			if (! file_exists($dir))
+			{
+				print '$dir'.$dir;
+				if (dol_mkdir($dir) < 0)
+				{
+					$this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir);
+					return -1;
+				}
+			}
+			
+
+			if (file_exists($dir))
+			{
+				//print "srctemplatepath=".$srctemplatepath;	// Src filename
+				$newfile=basename($srctemplatepath);
+				$newfiletmp=preg_replace('/\.odt/i','',$newfile);
+				$newfiletmp=preg_replace('/template_/i','',$newfiletmp);
+				$newfiletmp=preg_replace('/modele_/i','',$newfiletmp);
+				$newfiletmp=$objectref.'_'.$newfiletmp;
+				//$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt';
+				$file=$dir.'/'.$newfiletmp.'.odt';
+				//print "newdir=".$dir;
+				//print "newfile=".$newfile;
+				//print "file=".$file;
+				//print "conf->societe->dir_temp=".$conf->societe->dir_temp;
+
+				dol_mkdir($conf->projet->dir_temp);
+
+				$socobject=$object->thirdparty;
+
+				// Make substitution
+				$substitutionarray=array(
+				'__FROM_NAME__' => $this->emetteur->nom,
+				'__FROM_EMAIL__' => $this->emetteur->email,
+				);
+				complete_substitutions_array($substitutionarray, $langs, $object);
+
+				// Open and load template
+				require_once ODTPHP_PATH.'odf.php';
+				$odfHandler = new odf(
+					$srctemplatepath,
+					array(
+					'PATH_TO_TMP'	  => $conf->projet->dir_temp,
+					'ZIP_PROXY'		  => 'PclZipProxy',	// PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy.
+					'DELIMITER_LEFT'  => '{',
+					'DELIMITER_RIGHT' => '}'
+					)
+				);
+				// After construction $odfHandler->contentXml contains content and
+				// [!-- BEGIN row.lines --]*[!-- END row.lines --] has been replaced by
+				// [!-- BEGIN lines --]*[!-- END lines --]
+				//print html_entity_decode($odfHandler->__toString());
+				//print exit;
+
+
+
+
+				// Make substitutions into odt of user info
+				$tmparray=$this->get_substitutionarray_user($user,$outputlangs);
+				//var_dump($tmparray); exit;
+				foreach($tmparray as $key=>$value)
+				{
+					try {
+						if (preg_match('/logo$/',$key)) // Image
+						{
+							//var_dump($value);exit;
+							if (file_exists($value)) $odfHandler->setImage($key, $value);
+							else $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
+						}
+						else    // Text
+						{
+							$odfHandler->setVars($key, $value, true, 'UTF-8');
+						}
+					}
+					catch(OdfException $e)
+					{
+					}
+				}
+				// Make substitutions into odt of mysoc
+				$tmparray=$this->get_substitutionarray_mysoc($mysoc,$outputlangs);
+				//var_dump($tmparray); exit;
+				foreach($tmparray as $key=>$value)
+				{
+					try {
+						if (preg_match('/logo$/',$key))	// Image
+						{
+							//var_dump($value);exit;
+							if (file_exists($value)) $odfHandler->setImage($key, $value);
+							else $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
+						}
+						else	// Text
+						{
+							$odfHandler->setVars($key, $value, true, 'UTF-8');
+						}
+					}
+					catch(OdfException $e)
+					{
+					}
+				}
+
+				// Make substitutions into odt of thirdparty
+				$tmparray=$this->get_substitutionarray_thirdparty($socobject,$outputlangs);
+				foreach($tmparray as $key=>$value)
+				{
+					try {
+						if (preg_match('/logo$/',$key))	// Image
+						{
+							if (file_exists($value)) $odfHandler->setImage($key, $value);
+							else $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
+						}
+						else	// Text
+						{
+							$odfHandler->setVars($key, $value, true, 'UTF-8');
+							$odfHandler->setVarsHeadFooter($key, $value, true, 'UTF-8');
+						}
+					}
+					catch(OdfException $e)
+					{
+					}
+				}
+
+				// Replace tags of object + external modules
+				$tmparray=$this->get_substitutionarray_object($project,$outputlangs);
+				complete_substitutions_array($tmparray, $outputlangs, $object);
+				foreach($tmparray as $key=>$value)
+				{
+					try {
+						if (preg_match('/logo$/',$key)) // Image
+						{
+							if (file_exists($value)) $odfHandler->setImage($key, $value);
+							else $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
+						}
+						else    // Text
+						{
+							$odfHandler->setVars($key, $value, true, 'UTF-8');
+						}
+					}
+					catch(OdfException $e)
+					{
+					}
+				}
+
+				// Replace tags of lines for tasks
+				try
+				{
+					// Security check
+					$socid=0;
+					if (!empty($project->fk_soc)) $socid = $project->fk_soc;
+
+					$tmparray=$this->get_substitutionarray_tasks($object,$outputlangs);
+					complete_substitutions_array($tmparray, $outputlangs, $task);
+					foreach($tmparray as $key => $val)
+					{
+						try
+						{
+							$odfHandler->setVars($key, $val, true, 'UTF-8');
+						}
+						catch(OdfException $e)
+						{
+						}
+						catch(SegmentException $e)
+						{
+						}
+					}
+
+					// Replace tags of lines for contacts task
+					$sourcearray=array('internal','external');
+					$contact_arrray=array();
+					foreach ($sourcearray as $source) {
+						$contact_temp=$object->liste_contact(-1,$source);
+						if ((is_array($contact_temp) && count($contact_temp) > 0))
+						{
+							$contact_arrray=array_merge($contact_arrray,$contact_temp);
+						}
+					}
+					if ((is_array($contact_arrray) && count($contact_arrray) > 0))
+					{
+						$listlinestaskres = $odfHandler->setSegment('tasksressources');
+
+						foreach ($contact_arrray as $contact)
+						{
+							if ($contact['source']=='internal') {
+								$objectdetail=new User($this->db);
+								$objectdetail->fetch($contact['id']);
+								$contact['socname']=$mysoc->name;
+							} elseif ($contact['source']=='external') {
+								$objectdetail=new Contact($this->db);
+								$objectdetail->fetch($contact['id']);
+
+								$soc=new Societe($this->db);
+								$soc->fetch($contact['socid']);
+								$contact['socname']=$soc->name;
+							}
+							$contact['fullname']=$objectdetail->getFullName($outputlangs,1);
+
+							$tmparray=$this->get_substitutionarray_tasksressource($contact,$outputlangs);
+
+							foreach($tmparray as $key => $val)
+							{
+								try
+								{
+									$listlinestaskres->setVars($key, $val, true, 'UTF-8');
+								}
+								catch(OdfException $e)
+								{
+								}
+								catch(SegmentException $e)
+								{
+								}
+							}
+							$listlinestaskres->merge();
+						}
+						$odfHandler->mergeSegment($listlinestaskres);
+					}
+
+					//Time ressources
+					$sql = "SELECT t.rowid, t.task_date, t.task_duration, t.fk_user, t.note";
+					$sql.= ", u.name, u.firstname";
+					$sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as t";
+					$sql .= " , ".MAIN_DB_PREFIX."user as u";
+					$sql .= " WHERE t.fk_task =".$object->id;
+					$sql .= " AND t.fk_user = u.rowid";
+					$sql .= " ORDER BY t.task_date DESC";
+
+					$resql = $this->db->query($sql);
+					if ($resql)
+					{
+						$num = $this->db->num_rows($resql);
+						$i = 0;
+						$tasks = array();
+						$listlinestasktime = $odfHandler->setSegment('taskstimes');
+						while ($i < $num)
+						{
+							$row = $this->db->fetch_array($resql);
+							if (!empty($row['fk_user'])) {
+								$objectdetail=new User($this->db);
+								$objectdetail->fetch($row['fk_user']);
+								$row['fullcivname']=$objectdetail->getFullName($outputlangs,1);
+							} else {
+								$row['fullcivname']='';
+							}
+
+							$tmparray=$this->get_substitutionarray_taskstime($row,$outputlangs);
+
+							foreach($tmparray as $key => $val)
+							{
+								try
+								{
+									$listlinestasktime->setVars($key, $val, true, 'UTF-8');
+								}
+								catch(OdfException $e)
+								{
+								}
+								catch(SegmentException $e)
+								{
+								}
+							}
+							$listlinestasktime->merge();
+							$i++;
+						}
+						$this->db->free($resql);
+						
+						$odfHandler->mergeSegment($listlinestasktime);
+					}
+
+
+					// Replace tags of project files
+					$listtasksfiles = $odfHandler->setSegment('tasksfiles');
+
+					$upload_dir = $conf->projet->dir_output.'/'.dol_sanitizeFileName($project->ref).'/'.dol_sanitizeFileName($object->ref);
+					$filearray=dol_dir_list($upload_dir,"files",0,'','\.meta$','name',SORT_ASC,1);
+
+
+					foreach ($filearray as $filedetail)
+					{
+						$tmparray=$this->get_substitutionarray_task_file($filedetail,$outputlangs);
+						//dol_syslog(get_class($this).'::main $tmparray'.var_export($tmparray,true));
+						foreach($tmparray as $key => $val)
+						{
+							try
+							{
+								$listtasksfiles->setVars($key, $val, true, 'UTF-8');
+							}
+							catch(OdfException $e)
+							{
+							}
+							catch(SegmentException $e)
+							{
+							}
+						}
+						$listtasksfiles->merge();
+					}
+					//$listlines->merge();
+
+					$odfHandler->mergeSegment($listtasksfiles);
+						
+				}
+				catch(OdfException $e)
+				{
+					$this->error=$e->getMessage();
+					dol_syslog($this->error, LOG_WARNING);
+					return -1;
+				}
+
+
+
+				// Replace tags of project files
+				try
+				{
+					$listlines = $odfHandler->setSegment('projectfiles');
+
+					$upload_dir = $conf->projet->dir_output.'/'.dol_sanitizeFileName($object->ref);
+					$filearray=dol_dir_list($upload_dir,"files",0,'','\.meta$','name',SORT_ASC,1);
+
+
+					foreach ($filearray as $filedetail)
+					{
+						//dol_syslog(get_class($this).'::main $filedetail'.var_export($filedetail,true));
+						$tmparray=$this->get_substitutionarray_project_file($filedetail,$outputlangs);
+
+						foreach($tmparray as $key => $val)
+						{
+							try
+							{
+								$listlines->setVars($key, $val, true, 'UTF-8');
+							}
+							catch(OdfException $e)
+							{
+							}
+							catch(SegmentException $e)
+							{
+							}
+						}
+						$listlines->merge();
+					}
+					$odfHandler->mergeSegment($listlines);
+				}
+				catch(OdfException $e)
+				{
+					$this->error=$e->getMessage();
+					dol_syslog($this->error, LOG_WARNING);
+					return -1;
+				}
+
+				// Replace tags of lines for contacts
+				$sourcearray=array('internal','external');
+				$contact_arrray=array();
+				foreach ($sourcearray as $source) {
+					$contact_temp=$project->liste_contact(-1,$source);
+					if ((is_array($contact_temp) && count($contact_temp) > 0))
+					{
+						$contact_arrray=array_merge($contact_arrray,$contact_temp);
+					}
+				}
+				if ((is_array($contact_arrray) && count($contact_arrray) > 0))
+				{
+					try
+					{
+						$listlines = $odfHandler->setSegment('projectcontacts');
+
+						foreach ($contact_arrray as $contact)
+						{
+							if ($contact['source']=='internal') {
+								$objectdetail=new User($this->db);
+								$objectdetail->fetch($contact['id']);
+								$contact['socname']=$mysoc->name;
+							} elseif ($contact['source']=='external') {
+								$objectdetail=new Contact($this->db);
+								$objectdetail->fetch($contact['id']);
+
+								$soc=new Societe($this->db);
+								$soc->fetch($contact['socid']);
+								$contact['socname']=$soc->name;
+							}
+							$contact['fullname']=$objectdetail->getFullName($outputlangs,1);
+
+							$tmparray=$this->get_substitutionarray_project_contacts($contact,$outputlangs);
+								
+							foreach($tmparray as $key => $val)
+							{
+								try
+								{
+									$listlines->setVars($key, $val, true, 'UTF-8');
+								}
+								catch(OdfException $e)
+								{
+								}
+								catch(SegmentException $e)
+								{
+								}
+							}
+							$listlines->merge();
+						}
+						$odfHandler->mergeSegment($listlines);
+					}
+					catch(OdfException $e)
+					{
+						$this->error=$e->getMessage();
+						dol_syslog($this->error, LOG_WARNING);
+						return -1;
+					}
+				}
+
+
+				// Write new file
+				$odfHandler->saveToDisk($file);
+
+				if (! empty($conf->global->MAIN_UMASK))
+					@chmod($file, octdec($conf->global->MAIN_UMASK));
+
+				$odfHandler=null;	// Destroy object
+
+				return 1;   // Success
+			}
+			else
+			{
+				$this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir);
+				return -1;
+			}
+		}
+
+		return -1;
+	}
+
+}
+?>
\ No newline at end of file
diff --git a/htdocs/install/doctemplates/tasks/template_task_summary.odt b/htdocs/install/doctemplates/tasks/template_task_summary.odt
new file mode 100644
index 0000000000000000000000000000000000000000..76984ebcf8cb915a336d598a1899aa10abed260f
Binary files /dev/null and b/htdocs/install/doctemplates/tasks/template_task_summary.odt differ
diff --git a/htdocs/install/etape1.php b/htdocs/install/etape1.php
index 36b26fd795362858ab7cdf423651b3bfe1e111dc..f1aba6f52c2805b8b07e4b3e626e9e3b9d610e3f 100644
--- a/htdocs/install/etape1.php
+++ b/htdocs/install/etape1.php
@@ -402,7 +402,7 @@ if (! $error && $db->connected && $action == "set")
             	require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
             	$srcroot=$main_dir.'/install/doctemplates';
             	$destroot=$main_data_dir.'/doctemplates';
-            	$docs=array('thirdparties' => 'thirdparty', 'proposals' => 'proposal', 'orders' => 'order', 'invoices' => 'invoice', 'projects' => 'project', 'projects' => 'task_summary');
+            	$docs=array('thirdparties' => 'thirdparty', 'proposals' => 'proposal', 'orders' => 'order', 'invoices' => 'invoice', 'projects' => 'project', 'projects' => 'task_summary', 'tasks' => 'task_summary');
             	foreach($docs as $cursordir => $cursorfile)
             	{
             		$src=$srcroot.'/'.$cursordir.'/template_'.$cursorfile.'.odt';
diff --git a/htdocs/install/mysql/migration/3.4.0-3.5.0.sql b/htdocs/install/mysql/migration/3.4.0-3.5.0.sql
index e55f063ab15de44787d315ab8a889e3aa9cdab32..7e1f4086dd711ab80cc1d9a6ad4dec493ba0920a 100755
--- a/htdocs/install/mysql/migration/3.4.0-3.5.0.sql
+++ b/htdocs/install/mysql/migration/3.4.0-3.5.0.sql
@@ -90,4 +90,12 @@ ALTER TABLE llx_categorie_contact ADD INDEX idx_categorie_contact_fk_socpeople (
 ALTER TABLE llx_categorie_contact ADD CONSTRAINT fk_categorie_contact_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid);
 ALTER TABLE llx_categorie_contact ADD CONSTRAINT fk_categorie_contact_fk_socpeople   FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople (rowid);
 
+insert into llx_const (name, value, type, note, visible, entity) values ('PROJECT_TASK_ADDON_PDF','','chaine','Name of PDF/ODT tasks manager class',0,1);
+insert into llx_const (name, value, type, note, visible, entity) values ('PROJECT_TASK_ADDON','mod_task_simple','chaine','Name of Numbering Rule task manager class',0,1);
+insert into llx_const (name, value, type, note, visible, entity) values ('PROJECT_TASK_ADDON_PDF_ODT_PATH','DOL_DATA_ROOT/doctemplates/tasks','chaine','',0,1);
+
+ALTER TABLE llx_projet_task ADD COLUMN ref varchar(50) AFTER rowid;
+UPDATE llx_projet_task SET ref=rowid;
+ALTER TABLE llx_projet_task ADD COLUMN  model_pdf varchar(255);
+
 
diff --git a/htdocs/install/mysql/tables/llx_projet_task.sql b/htdocs/install/mysql/tables/llx_projet_task.sql
index 1fc7325bea079941222c0252eef57712f9004484..0c91a86b1a80d3667aa95eeaedfd7d7a188083be 100644
--- a/htdocs/install/mysql/tables/llx_projet_task.sql
+++ b/htdocs/install/mysql/tables/llx_projet_task.sql
@@ -29,8 +29,8 @@ create table llx_projet_task
   datev					datetime,						-- date validation
   label					varchar(255) NOT NULL,
   description			text,
-  duration_effective			real DEFAULT 0 NOT NULL,
-  planned_workload			real DEFAULT 0 NOT NULL,
+  duration_effective	real DEFAULT 0 NOT NULL,
+  planned_workload		real DEFAULT 0 NOT NULL,
   progress				integer	DEFAULT 0,				-- percentage increase
   priority				integer	DEFAULT 0,				-- priority
   fk_user_creat			integer,						-- user who created the task
@@ -38,5 +38,6 @@ create table llx_projet_task
   fk_statut				smallint DEFAULT 0 NOT NULL,
   note_private			text,
   note_public			text,
-  rang                  integer DEFAULT 0
+  rang                  integer DEFAULT 0,
+  model_pdf        		varchar(255)
 )ENGINE=innodb;
diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang
index 80f2d76557b551f76fcf9cf553f28045a201c4a5..34f04575546bf2eb6ceab83c822ecf1aa8c9c16c 100644
--- a/htdocs/langs/en_US/admin.lang
+++ b/htdocs/langs/en_US/admin.lang
@@ -1454,6 +1454,8 @@ TestGeoIPResult=Test of a conversion IP -> country
 ProjectsNumberingModules=Projects numbering module
 ProjectsSetup=Project module setup
 ProjectsModelModule=Project reports document model
+TasksNumberingModules=Tasks numbering module
+TaskModelModule=Tasks reports document model
 ##### ECM (GED) #####
 ECMSetup = GED Setup
 ECMAutoTree = Automatic tree folder and document  
diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang
index a057e02944ca24156570944bab5718d45a86e40e..1f4be3a3722cc49036ec4f78c8f5a431b3163ed3 100644
--- a/htdocs/langs/fr_FR/admin.lang
+++ b/htdocs/langs/fr_FR/admin.lang
@@ -1454,6 +1454,8 @@ TestGeoIPResult=Test de conversion IP -> Pays
 ProjectsNumberingModules=Modèles de numérotation des références projets
 ProjectsSetup=Configuration du module Projets
 ProjectsModelModule=Modèles de document de rapport projets
+TasksNumberingModules==Modèles de numérotation des références taches
+TaskModelModule=Modèles de document de rapport taches
 ##### ECM (GED) #####
 ECMSetup = Configuration du module GED
 ECMAutoTree = L'arborescence automatique est disponible
diff --git a/htdocs/projet/admin/project.php b/htdocs/projet/admin/project.php
index 036c2fae18bfb8afd9e7a1d12e7e8630eccb5a36..136e5124ca548611a8f3f5b56b9ea90c1f787309 100644
--- a/htdocs/projet/admin/project.php
+++ b/htdocs/projet/admin/project.php
@@ -68,6 +68,25 @@ if ($action == 'updateMask')
 	}
 }
 
+if ($action == 'updateMaskTask')
+{
+	$maskconstmasktask=GETPOST('maskconsttask','alpha');
+	$masktaskt=GETPOST('masktask','alpha');
+
+	if ($maskconstmasktask)  $res = dolibarr_set_const($db,$maskconstmasktask,$masktaskt,'chaine',0,'',$conf->entity);
+
+	if (! $res > 0) $error++;
+
+	if (! $error)
+	{
+		$mesg = "<font class=\"ok\">".$langs->trans("SetupSaved")."</font>";
+	}
+	else
+	{
+		$mesg = "<font class=\"error\">".$langs->trans("Error")."</font>";
+	}
+}
+
 else if ($action == 'specimen')
 {
 	$modele=GETPOST('module','alpha');
@@ -113,11 +132,61 @@ else if ($action == 'specimen')
 	}
 }
 
+else if ($action == 'specimentask')
+{
+	$modele=GETPOST('module','alpha');
+
+	$project = new Project($db);
+	$project->initAsSpecimen();
+
+	// Search template files
+	$file=''; $classname=''; $filefound=0;
+	$dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']);
+	foreach($dirmodels as $reldir)
+	{
+		$file=dol_buildpath($reldir."core/modules/project/task/pdf/pdf_".$modele.".modules.php",0);
+		if (file_exists($file))
+		{
+			$filefound=1;
+			$classname = "pdf_".$modele;
+			break;
+		}
+	}
+
+	if ($filefound)
+	{
+		require_once $file;
+
+		$module = new $classname($db);
+
+		if ($module->write_file($project,$langs) > 0)
+		{
+			header("Location: ".DOL_URL_ROOT."/document.php?modulepart=project_task&file=SPECIMEN.pdf");
+			return;
+		}
+		else
+		{
+			$mesg='<div class="error">'.$obj->error.'</div>';
+			dol_syslog($obj->error, LOG_ERR);
+		}
+	}
+	else
+	{
+		$mesg='<div class="error">'.$langs->trans("ErrorModuleNotFound").'</div>';
+		dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
+	}
+}
+
 // Activate a model
 else if ($action == 'set')
 {
 	$ret = addDocumentModel($value, $type, $label, $scandir);
 }
+// Activate a model for task
+else if ($action == 'settask')
+{
+	$ret = addDocumentModel($value,'project_task', $label, $scandir);
+}
 
 else if ($action == 'del')
 {
@@ -127,6 +196,14 @@ else if ($action == 'del')
 		if ($conf->global->PROJECT_ADDON_PDF == "$value") dolibarr_del_const($db, 'PROJECT_ADDON_PDF',$conf->entity);
 	}
 }
+if ($action == 'deltask')
+{
+	$ret = delDocumentModel($value, 'project_task');
+	if ($ret > 0)
+	{
+		if ($conf->global->PROJECT_TASK_ADDON_PDF == "$value") dolibarr_del_const($db, 'PROJECT_TASK_ADDON_PDF',$conf->entity);
+	}
+}
 
 // Set default model
 else if ($action == 'setdoc')
@@ -146,6 +223,23 @@ else if ($action == 'setdoc')
 	}
 }
 
+else if ($action == 'setdoctask')
+{
+	if (dolibarr_set_const($db, "PROJECT_TASK_ADDON_PDF",$value,'chaine',0,'',$conf->entity))
+	{
+		// La constante qui a ete lue en avant du nouveau set
+		// on passe donc par une variable pour avoir un affichage coherent
+		$conf->global->PROJECT_TASK_ADDON_PDF = $value;
+	}
+
+	// On active le modele
+	$ret = delDocumentModel($value, 'project_task');
+	if ($ret > 0)
+	{
+		$ret = addDocumentModel($value, 'project_task', $label, $scandir);
+	}
+}
+
 else if ($action == 'setmod')
 {
 	// TODO Verifier si module numerotation choisi peut etre active
@@ -154,6 +248,14 @@ else if ($action == 'setmod')
 	dolibarr_set_const($db, "PROJECT_ADDON",$value,'chaine',0,'',$conf->entity);
 }
 
+else if ($action == 'setmodtask')
+{
+	// TODO Verifier si module numerotation choisi peut etre active
+	// par appel methode canBeActivated
+
+	dolibarr_set_const($db, "PROJECT_TASK_ADDON",$value,'chaine',0,'',$conf->entity);
+}
+
 else if ($action=='setModuleOptions') {
 	if (dolibarr_set_const($db, "PROJECT_ADDON_PDF_ODT_PATH",GETPOST('value1'),'chaine',0,'',$conf->entity))
 	{
@@ -162,6 +264,15 @@ else if ($action=='setModuleOptions') {
 		$conf->global->PROJECT_ADDON_PDF_ODT_PATH = GETPOST('value1');
 	}
 }
+
+else if ($action=='setModuleOptionsTask') {
+	if (dolibarr_set_const($db, "PROJECT_TASK_ADDON_PDF_ODT_PATH",GETPOST('value1'),'chaine',0,'',$conf->entity))
+	{
+		// La constante qui a ete lue en avant du nouveau set
+		// on passe donc par une variable pour avoir un affichage coherent
+		$conf->global->PROJECT_TASK_ADDON_PDF_ODT_PATH = GETPOST('value1');
+	}
+}
 /*
  * View
 */
@@ -285,6 +396,106 @@ foreach ($dirmodels as $reldir)
 
 print '</table><br>';
 
+// Task numbering module
+print_titre($langs->trans("TasksNumberingModules"));
+
+print '<table class="noborder" width="100%">';
+print '<tr class="liste_titre">';
+print '<td width="100">'.$langs->trans("Name").'</td>';
+print '<td>'.$langs->trans("Description").'</td>';
+print '<td>'.$langs->trans("Example").'</td>';
+print '<td align="center" width="60">'.$langs->trans("Activated").'</td>';
+print '<td align="center" width="80">'.$langs->trans("Infos").'</td>';
+print "</tr>\n";
+
+clearstatcache();
+
+foreach ($dirmodels as $reldir)
+{
+	$dir = dol_buildpath($reldir."core/modules/project/task/");
+
+	if (is_dir($dir))
+	{
+		$handle = opendir($dir);
+		if (is_resource($handle))
+		{
+			$var=true;
+
+			while (($file = readdir($handle))!==false)
+			{
+				if (preg_match('/^(mod_.*)\.php$/i',$file,$reg))
+				{
+					$file = $reg[1];
+					$classname = substr($file,4);
+
+					require_once DOL_DOCUMENT_ROOT ."/core/modules/project/task/".$file.'.php';
+
+					$module = new $file;
+
+					// Show modules according to features level
+					if ($module->version == 'development'  && $conf->global->MAIN_FEATURES_LEVEL < 2) continue;
+					if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue;
+
+					if ($module->isEnabled())
+					{
+						$var=!$var;
+						print '<tr '.$bc[$var].'><td>'.$module->nom."</td><td>\n";
+						print $module->info();
+						print '</td>';
+
+						// Show example of numbering module
+						print '<td nowrap="nowrap">';
+						$tmp=$module->getExample();
+						if (preg_match('/^Error/',$tmp)) print '<div class="error">'.$langs->trans($tmp).'</div>';
+						elseif ($tmp=='NotConfigured') print $langs->trans($tmp);
+						else print $tmp;
+						print '</td>'."\n";
+
+						print '<td align="center">';
+						if ($conf->global->PROJECT_TASK_ADDON == 'mod_'.$classname)
+						{
+							print img_picto($langs->trans("Activated"),'switch_on');
+						}
+						else
+						{
+							print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmodtask&amp;value=mod_'.$classname.'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'switch_off').'</a>';
+						}
+						print '</td>';
+
+						$project=new Project($db);
+						$project->initAsSpecimen();
+
+						// Info
+						$htmltooltip='';
+						$htmltooltip.=''.$langs->trans("Version").': <b>'.$module->getVersion().'</b><br>';
+						$nextval=$module->getNextValue($mysoc,$project);
+						if ("$nextval" != $langs->trans("NotAvailable"))	// Keep " on nextval
+						{
+							$htmltooltip.=''.$langs->trans("NextValue").': ';
+							if ($nextval)
+							{
+								$htmltooltip.=$nextval.'<br>';
+							}
+							else
+							{
+								$htmltooltip.=$langs->trans($module->error).'<br>';
+							}
+						}
+
+						print '<td align="center">';
+						print $form->textwithpicto('',$htmltooltip,1,0);
+						print '</td>';
+
+						print '</tr>';
+					}
+				}
+			}
+			closedir($handle);
+		}
+	}
+}
+
+print '</table><br>';
 
 /*
  * Document templates generators
@@ -412,6 +623,143 @@ foreach ($dirmodels as $reldir)
 							}
 							print '</td>';
 
+							print "</tr>\n";
+                        }
+					}
+				}
+			}
+			closedir($handle);
+		}
+	}
+}
+
+print '</table><br/>';
+
+/*
+ * Modeles documents for Task
+*/
+
+print_titre($langs->trans("TaskModelModule"));
+
+// Defini tableau def de modele
+$type='project_task';
+$def = array();
+
+$sql = "SELECT nom";
+$sql.= " FROM ".MAIN_DB_PREFIX."document_model";
+$sql.= " WHERE type = '".$type."'";
+$sql.= " AND entity = ".$conf->entity;
+
+$resql=$db->query($sql);
+if ($resql)
+{
+	$i = 0;
+	$num_rows=$db->num_rows($resql);
+	while ($i < $num_rows)
+	{
+		$array = $db->fetch_array($resql);
+		array_push($def, $array[0]);
+		$i++;
+	}
+}
+else
+{
+	dol_print_error($db);
+}
+
+print "<table class=\"noborder\" width=\"100%\">\n";
+print "<tr class=\"liste_titre\">\n";
+print '  <td width="100">'.$langs->trans("Name")."</td>\n";
+print "  <td>".$langs->trans("Description")."</td>\n";
+print '<td align="center" width="60">'.$langs->trans("Activated")."</td>\n";
+print '<td align="center" width="60">'.$langs->trans("Default")."</td>\n";
+print '<td align="center" width="80">'.$langs->trans("Infos").'</td>';
+print "</tr>\n";
+
+clearstatcache();
+
+$var=true;
+foreach ($dirmodels as $reldir)
+{
+	$dir = dol_buildpath($reldir."core/modules/project/task/pdf/");
+
+	if (is_dir($dir))
+	{
+		$handle=opendir($dir);
+		if (is_resource($handle))
+		{
+			while (($file = readdir($handle))!==false)
+			{
+				if (preg_match('/\.modules\.php$/i',$file) && preg_match('/^(pdf_|doc_)/',$file))
+				{
+					if (file_exists($dir.'/'.$file))
+					{
+						$name = substr($file, 4, dol_strlen($file) -16);
+						$classname = substr($file, 0, dol_strlen($file) -12);
+
+						require_once $dir.'/'.$file;
+						$module = new $classname($db);
+
+						$modulequalified=1;
+						if ($module->version == 'development'  && $conf->global->MAIN_FEATURES_LEVEL < 2) $modulequalified=0;
+						if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) $modulequalified=0;
+
+						if ($modulequalified)
+						{
+							$var = !$var;
+							print '<tr '.$bc[$var].'><td width="100">';
+							print (empty($module->name)?$name:$module->name);
+							print "</td><td>\n";
+							if (method_exists($module,'info')) print $module->info($langs);
+							else print $module->description;
+							print "</td>\n";
+
+							// Active
+							if (in_array($name, $def))
+							{
+								print "<td align=\"center\">\n";
+								print '<a href="'.$_SERVER["PHP_SELF"].'?action=deltask&amp;value='.$name.'&amp;scandir='.$module->scandir.'&amp;label='.urlencode($module->name).'">';
+								print img_picto($langs->trans("Enabled"),'switch_on');
+								print '</a>';
+								print "</td>";
+							}
+							else
+							{
+								print "<td align=\"center\">\n";
+								print '<a href="'.$_SERVER["PHP_SELF"].'?action=settask&amp;value='.$name.'&amp;scandir='.$module->scandir.'&amp;label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"),'switch_off').'</a>';
+								print "</td>";
+							}
+
+							// Defaut
+							print "<td align=\"center\">";
+							if ($conf->global->PROJECT_TASK_ADDON_PDF == "$name")
+							{
+								print img_picto($langs->trans("Default"),'on');
+							}
+							else
+							{
+								print '<a href="'.$_SERVER["PHP_SELF"].'?action=setdoctask&amp;value='.$name.'&amp;scandir='.$module->scandir.'&amp;label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'off').'</a>';
+							}
+							print '</td>';
+
+							// Info
+							$htmltooltip =    ''.$langs->trans("Name").': '.$module->name;
+							$htmltooltip.='<br>'.$langs->trans("Type").': '.($module->type?$module->type:$langs->trans("Unknown"));
+							$htmltooltip.='<br>'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur;
+							$htmltooltip.='<br><br><u>'.$langs->trans("FeaturesSupported").':</u>';
+							$htmltooltip.='<br>'.$langs->trans("Logo").': '.yn($module->option_logo,1,1);
+								
+							// Preview
+							print '<td align="center">';
+							if ($module->type == 'pdf')
+							{
+								print '<a href="'.$_SERVER["PHP_SELF"].'?action=specimentask&module='.$name.'">'.img_object($langs->trans("Preview"),'bill').'</a>';
+							}
+							else
+							{
+								print img_object($langs->trans("PreviewNotAvailable"),'generic');
+							}
+							print '</td>';
 							print "</tr>\n";
 						}
 					}
diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php
index 94f6137c49b903eaa3bd0b42f42b88a1ef0fe4b4..d7c332aba164f45774678b2b4a35b11b2c126448 100644
--- a/htdocs/projet/class/task.class.php
+++ b/htdocs/projet/class/task.class.php
@@ -36,6 +36,8 @@ class Task extends CommonObject
 
     var $id;
 
+	var $ref;
+
     var $fk_project;
     var $fk_task_parent;
     var $label;
@@ -52,6 +54,7 @@ class Task extends CommonObject
     var $statut;
     var $note_private;
     var $note_public;
+	var $rang;
 
     var $timespent_id;
     var $timespent_duration;
@@ -95,6 +98,7 @@ class Task extends CommonObject
         // Insert request
         $sql = "INSERT INTO ".MAIN_DB_PREFIX."projet_task (";
         $sql.= "fk_projet";
+		$sql.= ", ref";
         $sql.= ", fk_task_parent";
         $sql.= ", label";
         $sql.= ", description";
@@ -106,6 +110,7 @@ class Task extends CommonObject
         $sql.= ", progress";
         $sql.= ") VALUES (";
         $sql.= $this->fk_project;
+		$sql.= ", ".(!empty($this->ref)?"'".$this->db->escape($this->ref)."'":'null');
         $sql.= ", ".$this->fk_task_parent;
         $sql.= ", '".$this->db->escape($this->label)."'";
         $sql.= ", '".$this->db->escape($this->description)."'";
@@ -173,14 +178,16 @@ class Task extends CommonObject
      *  Load object in memory from database
      *
      *  @param	int		$id			Id object
+     *  @param	int		$ref		ref object
      *  @return int 		        <0 if KO, >0 if OK
      */
-    function fetch($id)
+    function fetch($id,$ref='')
     {
         global $langs;
 
         $sql = "SELECT";
         $sql.= " t.rowid,";
+		$sql.= " t.ref,";
         $sql.= " t.fk_projet,";
         $sql.= " t.fk_task_parent,";
         $sql.= " t.label,";
@@ -196,9 +203,15 @@ class Task extends CommonObject
         $sql.= " t.progress,";
         $sql.= " t.priority,";
         $sql.= " t.note_private,";
-        $sql.= " t.note_public";
+		$sql.= " t.note_public,";
+		$sql.= " t.rang";
         $sql.= " FROM ".MAIN_DB_PREFIX."projet_task as t";
-        $sql.= " WHERE t.rowid = ".$id;
+        $sql.= " WHERE ";
+        if (!empty($ref)) {
+        	$sql.="t.ref = '".$ref."'";
+        }else {
+        	$sql.="t.rowid = ".$id;
+        }
 
         dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG);
         $resql=$this->db->query($sql);
@@ -209,7 +222,7 @@ class Task extends CommonObject
                 $obj = $this->db->fetch_object($resql);
 
                 $this->id					= $obj->rowid;
-                $this->ref					= $obj->rowid;
+				$this->ref					= $obj->ref;
                 $this->fk_project			= $obj->fk_projet;
                 $this->fk_task_parent		= $obj->fk_task_parent;
                 $this->label				= $obj->label;
@@ -226,6 +239,7 @@ class Task extends CommonObject
                 $this->priority				= $obj->priority;
                 $this->note_private			= $obj->note_private;
                 $this->note_public			= $obj->note_public;
+				$this->rang					= $obj->rang;
             }
 
             $this->db->free($resql);
@@ -255,6 +269,7 @@ class Task extends CommonObject
 
         // Clean parameters
         if (isset($this->fk_project)) $this->fk_project=trim($this->fk_project);
+		if (isset($this->ref)) $this->ref=trim($this->ref);
         if (isset($this->fk_task_parent)) $this->fk_task_parent=trim($this->fk_task_parent);
         if (isset($this->label)) $this->label=trim($this->label);
         if (isset($this->description)) $this->description=trim($this->description);
@@ -267,6 +282,7 @@ class Task extends CommonObject
         // Update request
         $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task SET";
         $sql.= " fk_projet=".(isset($this->fk_project)?$this->fk_project:"null").",";
+		$sql.= " ref=".(isset($this->ref)?"'".$this->db->escape($this->ref)."'":"'".$this->id."'").",";
         $sql.= " fk_task_parent=".(isset($this->fk_task_parent)?$this->fk_task_parent:"null").",";
         $sql.= " label=".(isset($this->label)?"'".$this->db->escape($this->label)."'":"null").",";
         $sql.= " description=".(isset($this->description)?"'".$this->db->escape($this->description)."'":"null").",";
@@ -274,7 +290,8 @@ class Task extends CommonObject
         $sql.= " planned_workload=".(isset($this->planned_workload)?$this->planned_workload:"0").",";
         $sql.= " dateo=".($this->date_start!=''?$this->db->idate($this->date_start):'null').",";
         $sql.= " datee=".($this->date_end!=''?$this->db->idate($this->date_end):'null').",";
-        $sql.= " progress=".$this->progress;
+        $sql.= " progress=".$this->progress.",";
+        $sql.= " rang=".((!empty($this->rang))?$this->rang:"0");
         $sql.= " WHERE rowid=".$this->id;
 
         $this->db->begin();
@@ -500,6 +517,7 @@ class Task extends CommonObject
         $this->id=0;
 
         $this->fk_projet='';
+		$this->ref='';
         $this->fk_task_parent='';
         $this->title='';
         $this->duration_effective='';
@@ -531,7 +549,7 @@ class Task extends CommonObject
         // List of tasks (does not care about permissions. Filtering will be done later)
         $sql = "SELECT p.rowid as projectid, p.ref, p.title as plabel, p.public,";
         $sql.= " t.rowid as taskid, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress,";
-        $sql.= " t.dateo as date_start, t.datee as date_end, t.planned_workload";
+        $sql.= " t.dateo as date_start, t.datee as date_end, t.planned_workload, t.ref as ref_task,t.rang";
         if ($mode == 0)
         {
             $sql.= " FROM ".MAIN_DB_PREFIX."projet as p";
@@ -583,9 +601,9 @@ class Task extends CommonObject
 
                 if (! $error)
                 {
-                	$tasks[$i]					= new stdClass();
+					$tasks[$i] = new Task($db);
                     $tasks[$i]->id				= $obj->taskid;
-                    $tasks[$i]->ref				= $obj->taskid;
+					$tasks[$i]->ref				= $obj->ref_task;
                     $tasks[$i]->fk_project		= $obj->projectid;
                     $tasks[$i]->projectref		= $obj->ref;
                     $tasks[$i]->projectlabel	= $obj->plabel;
@@ -598,6 +616,7 @@ class Task extends CommonObject
                     $tasks[$i]->public			= $obj->public;
                     $tasks[$i]->date_start		= $this->db->jdate($obj->date_start);
                     $tasks[$i]->date_end		= $this->db->jdate($obj->date_end);
+                    $tasks[$i]->rang	   		= $obj->rang;
                 }
 
                 $i++;
@@ -993,19 +1012,32 @@ class Task extends CommonObject
 		$datec = $now;
 
 		$clone_task=new Task($this->db);
+		$origin_task=new Task($this->db);
 
 		$this->db->begin();
 
 		// Load source object
 		$clone_task->fetch($fromid);
+		$origin_task->fetch($fromid);
+		
+		$defaultref='';
+		$obj = empty($conf->global->PROJECT_TASK_ADDON)?'mod_task_simple':$conf->global->PROJECT_TASK_ADDON;
+		if (! empty($conf->global->PROJECT_TASK_ADDON) && is_readable(DOL_DOCUMENT_ROOT ."/core/modules/project/task/".$conf->global->PROJECT_TASK_ADDON.".php"))
+		{
+			require_once DOL_DOCUMENT_ROOT ."/core/modules/project/task/".$conf->global->PROJECT_TASK_ADDON.'.php';
+			$modTask = new $obj;
+			$defaultref = $modTask->getNextValue(0,$clone_task);
+		}
 
 		$ori_project_id					= $clone_task->fk_project;
 
 		$clone_task->id					= 0;
+		$clone_task->ref				= $defaultref;
         $clone_task->fk_project			= $project_id;
         $clone_task->fk_task_parent		= $parent_task_id;
         $clone_task->date_c				= $datec;
         $clone_task->planned_workload	= $clone_task->planned_workload;
+		$clone_task->rang				= $origin_task->rang;
 
         //Manage Task Date
         if ($clone_change_dt)
diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php
index 152c604048eee87a30835a17dc448fdccab50e16..fc29a748dbeb09a661ec4e1002896feb403f112b 100644
--- a/htdocs/projet/tasks.php
+++ b/htdocs/projet/tasks.php
@@ -114,6 +114,7 @@ if ($action == 'createtask' && $user->rights->projet->creer)
 			$task = new Task($db);
 
 			$task->fk_project = $projectid;
+			$task->ref = GETPOST('ref','alpha');
 			$task->label = $label;
 			$task->description = $description;
 			$task->planned_workload = $planned_workload * 3600;//We set the planned workload into seconds
@@ -170,6 +171,7 @@ if ($action == 'createtask' && $user->rights->projet->creer)
 
 $form=new Form($db);
 $formother=new FormOther($db);
+$taskstatic = new Task($db);
 $userstatic=new User($db);
 
 $help_url="EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos";
@@ -266,11 +268,27 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->socie
 	print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 	print '<input type="hidden" name="action" value="createtask">';
 	print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
+	
 	if (! empty($object->id)) print '<input type="hidden" name="id" value="'.$object->id.'">';
 	if (! empty($mode)) print '<input type="hidden" name="mode" value="'.$mode.'">';
 
 	print '<table class="border" width="100%">';
 
+	$defaultref='';
+	$obj = empty($conf->global->PROJECT_TASK_ADDON)?'mod_task_simple':$conf->global->PROJECT_TASK_ADDON;
+	if (! empty($conf->global->PROJECT_TASK_ADDON) && is_readable(DOL_DOCUMENT_ROOT ."/core/modules/project/task/".$conf->global->PROJECT_TASK_ADDON.".php"))
+	{
+		require_once DOL_DOCUMENT_ROOT ."/core/modules/project/task/".$conf->global->PROJECT_TASK_ADDON.'.php';
+		$modTask = new $obj;
+		$defaultref = $modTask->getNextValue($soc,$object);
+	}
+		
+	if (is_numeric($defaultref) && $defaultref <= 0) $defaultref='';
+		
+	// Ref
+	print '<input type="hidden" name="ref" value="'.($_POST["ref"]?$_POST["ref"]:$defaultref).'">';
+	print '<tr><td><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td>'.($_POST["ref"]?$_POST["ref"]:$defaultref).'</td></tr>';
+
 	print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td><td>';
 	print '<input type="text" size="25" name="label" class="flat" value="'.$label.'">';
 	print '</td></tr>';
@@ -394,7 +412,7 @@ else
 	print '<table id="tablelines" class="noborder" width="100%">';
 	print '<tr class="liste_titre">';
 	// print '<td>'.$langs->trans("Project").'</td>';
-	print '<td width="80">'.$langs->trans("RefTask").'</td>';
+	print '<td width="100">'.$langs->trans("RefTask").'</td>';
 	print '<td>'.$langs->trans("LabelTask").'</td>';
 	print '<td align="center">'.$langs->trans("DateStart").'</td>';
 	print '<td align="center">'.$langs->trans("DateEnd").'</td>';
diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php
index 858e4612f1af88cf1e88c005d7e50603113dee41..f95d93d98be5393aabf696ef4980a121b112af5b 100644
--- a/htdocs/projet/tasks/task.php
+++ b/htdocs/projet/tasks/task.php
@@ -23,6 +23,10 @@
  *	\brief      Page of a project task
  */
 
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+ini_set('html_errors', false);
+
 require ("../../main.inc.php");
 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
@@ -30,6 +34,11 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/modules/project/task/modules_task.php';
+
+$langs->load("projects");
+$langs->load("companies");
 
 $id=GETPOST('id','int');
 $ref=GETPOST('ref','alpha');
@@ -68,7 +77,7 @@ if ($action == 'update' && ! $_POST["cancel"] && $user->rights->projet->creer)
 	}
 	if (! $error)
 	{
-		$object->fetch($id);
+		$object->fetch($id,$ref);
 
 		$tmparray=explode('_',$_POST['task_parent']);
 		$task_parent=$tmparray[1];
@@ -95,7 +104,7 @@ if ($action == 'update' && ! $_POST["cancel"] && $user->rights->projet->creer)
 
 if ($action == 'confirm_delete' && $confirm == "yes" && $user->rights->projet->supprimer)
 {
-	if ($object->fetch($id) >= 0 )
+	if ($object->fetch($id,$ref) >= 0 )
 	{
 		$result=$projectstatic->fetch($object->fk_projet);
 		if (! empty($projectstatic->socid))
@@ -134,20 +143,67 @@ if (! empty($project_ref) && ! empty($withproject))
 	}
 }
 
+// Build doc
+if ($action == 'builddoc' && $user->rights->projet->creer)
+{
+	if ($object->fetch($id,$ref) >= 0 )
+	{
+		if (GETPOST('model'))
+		{
+			$object->setDocModel($user, GETPOST('model'));
+		}
+
+		$outputlangs = $langs;
+		if (GETPOST('lang_id'))
+		{
+			$outputlangs = new Translate("",$conf);
+			$outputlangs->setDefaultLang(GETPOST('lang_id'));
+		}
+		$result=task_pdf_create($db, $object, $object->modelpdf, $outputlangs);
+		if ($result <= 0)
+		{
+			dol_print_error($db,$result);
+			exit;
+		}
+		else
+		{
+			header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id.(empty($conf->global->MAIN_JUMP_TAG)?'':'#builddoc'));
+			exit;
+		}
+	}
+}
+
+// Delete file in doc form
+if ($action == 'remove_file' && $user->rights->projet->creer)
+{
+	require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+
+	if ($object->fetch($id,$ref) >= 0 )
+	{
+		$langs->load("other");
+		$upload_dir =	$conf->projet->dir_output;
+		$file =	$upload_dir	. '/' .	GETPOST('file');
+
+		$ret=dol_delete_file($file);
+		if ($ret) setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile')));
+		else setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors');
+	}
+}
+
 /*
  * View
 */
 
-$langs->load('projects');
 
 llxHeader('', $langs->trans("Task"));
 
 $form = new Form($db);
 $formother = new FormOther($db);
+$formfile = new FormFile($db);
 
 if ($id > 0 || ! empty($ref))
 {
-	if ($object->fetch($id) > 0)
+	if ($object->fetch($id,$ref) > 0)
 	{
 		$res=$object->fetch_optionals($object->id,$extralabels);
 
@@ -345,7 +401,7 @@ if ($id > 0 || ! empty($ref))
 				$object->next_prev_filter=" fk_projet in (".$projectsListId.")";
 			}
 			else $object->next_prev_filter=" fk_projet = ".$projectstatic->id;
-			print $form->showrefnav($object,'id',$linkback,1,'rowid','ref','',$param);
+			print $form->showrefnav($object,'ref',$linkback,1,'ref','ref','',$param);
 			print '</td>';
 			print '</tr>';
 
@@ -434,6 +490,26 @@ if ($id > 0 || ! empty($ref))
 			}
 
 			print '</div>';
+			
+			print '<table width="100%"><tr><td width="50%" valign="top">';
+			print '<a name="builddoc"></a>'; // ancre
+			
+			/*
+			 * Documents generes
+			*/
+			$filename=dol_sanitizeFileName($projectstatic->ref). "/". dol_sanitizeFileName($object->ref);
+			$filedir=$conf->projet->dir_output . "/" . dol_sanitizeFileName($projectstatic->ref). "/" .dol_sanitizeFileName($object->ref);
+			$urlsource=$_SERVER["PHP_SELF"]."?id=".$object->id;
+			$genallowed=($user->rights->projet->lire);
+			$delallowed=($user->rights->projet->creer);
+				
+			$var=true;
+				
+			$somethingshown=$formfile->show_documents('project_task',$filename,$filedir,$urlsource,$genallowed,$delallowed,$object->modelpdf);
+			
+				
+				
+			print '</td></tr></table>';
 		}
 	}
 }