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"> <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"> ';
+ $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&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&value='.$name.'&scandir='.$module->scandir.'&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&value='.$name.'&scandir='.$module->scandir.'&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&value='.$name.'&scandir='.$module->scandir.'&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ó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>';
}
}
}