diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index d5d52761140..e8ce515317f 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -328,6 +328,11 @@ function product_lot_admin_prepare_head() $h = 0; $head = array(); + $head[$h][0] = DOL_URL_ROOT."/product/admin/product_lot.php"; + $head[$h][1] = $langs->trans('Parameters'); + $head[$h][2] = 'settings'; + $h++; + // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab diff --git a/htdocs/core/modules/modProductBatch.class.php b/htdocs/core/modules/modProductBatch.class.php index 781948d0f52..aec35c1b53c 100644 --- a/htdocs/core/modules/modProductBatch.class.php +++ b/htdocs/core/modules/modProductBatch.class.php @@ -65,7 +65,7 @@ class modProductBatch extends DolibarrModules $this->dirs = array(); // Config pages. Put here list of php page, stored into productdluo/admin directory, to use to setup module. - $this->config_page_url = array("product_lot_extrafields.php@product"); + $this->config_page_url = array("product_lot.php@product"); // Dependencies $this->hidden = false; // A condition to hide module diff --git a/htdocs/core/modules/product_batch/mod_batch_advanced.php b/htdocs/core/modules/product_batch/mod_batch_advanced.php new file mode 100644 index 00000000000..cdf0ce3a70b --- /dev/null +++ b/htdocs/core/modules/product_batch/mod_batch_advanced.php @@ -0,0 +1,147 @@ + + * Copyright (C) 2004-2007 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2008 Raphael Bertrand (Resultic) + * Copyright (C) 2019 Frédéric France + * Copyright (C) 2021 Christophe Battarel + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/product_batch/mod_batch_advanced.php + * \ingroup productbatch + * \brief File containing class for numbering model of Batch advanced + */ + +require_once DOL_DOCUMENT_ROOT.'/core/modules/product_batch/modules_product_batch.class.php'; + + +/** + * Class to manage Batch numbering rules advanced + */ +class mod_batch_advanced extends ModeleNumRefBatch +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + /** + * @var string Error message + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'advanced'; + + + /** + * Returns the description of the numbering model + * + * @return string Texte descripif + */ + public function info() + { + global $conf, $langs, $db; + + $langs->load("bills"); + + $form = new Form($db); + + $texte = $langs->trans('GenericNumRefModelDesc')."
\n"; + $texte .= '
'; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + + $tooltip = $langs->trans("GenericMaskCodes", $langs->transnoentities("Batch"), $langs->transnoentities("Batch")); + $tooltip .= $langs->trans("GenericMaskCodes2"); + $tooltip .= $langs->trans("GenericMaskCodes3"); + $tooltip .= $langs->trans("GenericMaskCodes4a", $langs->transnoentities("Batch"), $langs->transnoentities("Batch")); + $tooltip .= $langs->trans("GenericMaskCodes5"); + + // Parametrage du prefix + $texte .= ''; + $texte .= ''; + + $texte .= ''; + + $texte .= ''; + + $texte .= '
'.$langs->trans("Mask").':'.$form->textwithpicto('', $tooltip, 1, 1).' 
'; + $texte .= '
'; + + return $texte; + } + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample() + { + global $conf, $langs, $mysoc; + + $old_code_client = $mysoc->code_client; + $old_code_type = $mysoc->typent_code; + $mysoc->code_client = 'CCCCCCCCCC'; + $mysoc->typent_code = 'TTTTTTTTTT'; + $numExample = $this->getNextValue($mysoc, ''); + $mysoc->code_client = $old_code_client; + $mysoc->typent_code = $old_code_type; + + if (!$numExample) + { + $numExample = $langs->trans('NotConfigured'); + } + return $numExample; + } + + /** + * Return next free value + * + * @param Product $objprod Object product + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + */ + public function getNextValue($objprod, $object) + { + global $db, $conf; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + + // We get cursor rule + $mask = $conf->global->BATCH_ADVANCED_MASK; + + if (!$mask) + { + $this->error = 'NotConfigured'; + return 0; + } + + $date = $object->date; + + $numFinal = get_next_value($db, $mask, 'product_lot', 'ref', '', null, $date); + + return $numFinal; + } +} diff --git a/htdocs/core/modules/product_batch/mod_batch_free.php b/htdocs/core/modules/product_batch/mod_batch_free.php new file mode 100644 index 00000000000..13df9b11a55 --- /dev/null +++ b/htdocs/core/modules/product_batch/mod_batch_free.php @@ -0,0 +1,113 @@ + + * Copyright (C) 2006-2009 Laurent Destailleur + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/product/mod_batch_free.php + * \ingroup product + * \brief Fichier de la classe des gestion leopard des codes produits + */ + +require_once DOL_DOCUMENT_ROOT.'/core/modules/product_batch/modules_product_batch.class.php'; + +/** + * \class mod_codeproduct_leopard + * \brief Classe permettant la gestion leopard des codes produits + */ +class mod_batch_free extends ModeleNumRefBatch +{ + /* + * Attention ce module est utilise par defaut si aucun module n'a + * ete definit dans la configuration + * + * Le fonctionnement de celui-ci doit donc rester le plus ouvert possible + */ + + /** + * @var string Nom du modele + * @deprecated + * @see $name + */ + public $nom = 'Free'; + + /** + * @var string model name + */ + public $name = 'Free'; + + public $code_modifiable; // Code modifiable + + public $code_modifiable_invalide; // Code modifiable si il est invalide + + public $code_modifiable_null; // Code modifiables si il est null + + public $code_null; // Code facultatif + + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + /** + * @var int Automatic numbering + */ + public $code_auto; + + + /** + * Constructor + */ + public function __construct() + { + $this->code_null = 1; + $this->code_modifiable = 1; + $this->code_modifiable_invalide = 1; + $this->code_modifiable_null = 1; + $this->code_auto = 0; + } + + + /** + * Return description of module + * + * @param Translate $langs Object langs + * @return string Description of module + */ + public function info() + { + global $langs; + $langs->load("companies"); + return $langs->trans("LeopardNumRefModelDesc"); + } + + + /** + * Return an example of result returned by getNextValue + * + * @param product $objproduct Object product + * @param int $type Type of third party (1:customer, 2:supplier, -1:autodetect) + * @return string Return next value + */ + public function getNextValue($objproduct = 0, $type = -1) + { + global $langs; + return ''; + } + +} diff --git a/htdocs/core/modules/product_batch/mod_batch_lot.php b/htdocs/core/modules/product_batch/mod_batch_lot.php new file mode 100644 index 00000000000..ceca5c16e08 --- /dev/null +++ b/htdocs/core/modules/product_batch/mod_batch_lot.php @@ -0,0 +1,150 @@ + + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2021 Christophe Battarel + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/product_batch/mod_batch_lot.php + * \ingroup productbatch + * \brief File of class to manage MO numbering rules standard + */ +require_once DOL_DOCUMENT_ROOT.'/core/modules/product_batch/modules_product_batch.class.php'; + +/** + * Class to manage MO numbering rules standard + */ +class mod_batch_lot extends ModeleNumRefBatch +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + public $prefix = 'LOT'; + + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'Lot number'; + + + /** + * Return description of numbering module + * + * @return string Text with description + */ + public function info() + { + global $langs; + return $langs->trans("SimpleNumRefModelDesc", $this->prefix); + } + + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample() + { + return $this->prefix."0501-0001"; + } + + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @return boolean false if conflict, true if ok + */ + public function canBeActivated() + { + global $conf, $langs, $db; + + $coyymm = ''; $max = ''; + + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."product_lot"; + $sql .= " WHERE ref LIKE '".$db->escape($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)) + { + $langs->load("errors"); + $this->error = $langs->trans('ErrorNumRefModel', $max); + return false; + } + + return true; + } + + /** + * Return next free value + * + * @param Product $objprod Object product + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + */ + public function getNextValue($objprod, $object) + { + global $db, $conf; + + // First, we get the max value + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."product_lot"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + $sql .= " AND entity = ".$conf->entity; + + $resql = $db->query($sql); + if ($resql) + { + $obj = $db->fetch_object($resql); + if ($obj) $max = intval($obj->max); + else $max = 0; + } + else + { + dol_syslog("mod_mo_standard::getNextValue", LOG_DEBUG); + return -1; + } + + //$date=time(); + $date = $object->date_creation; + $yymm = strftime("%y%m", $date); + + if ($max >= (pow(10, 4) - 1)) $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is + else $num = sprintf("%04s", $max + 1); + + dol_syslog("mod_mo_standard::getNextValue return ".$this->prefix.$yymm."-".$num); + return $this->prefix.$yymm."-".$num; + } +} diff --git a/htdocs/core/modules/product_batch/mod_batch_sn.php b/htdocs/core/modules/product_batch/mod_batch_sn.php new file mode 100644 index 00000000000..43fa2e2a06e --- /dev/null +++ b/htdocs/core/modules/product_batch/mod_batch_sn.php @@ -0,0 +1,150 @@ + + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2021 Christophe Battarel + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/modules/product_batch/mod_batch_sn.php + * \ingroup productbatch + * \brief File of class to manage MO numbering rules standard + */ +require_once DOL_DOCUMENT_ROOT.'/core/modules/product_batch/modules_product_batch.class.php'; + +/** + * Class to manage MO numbering rules standard + */ +class mod_batch_sn extends ModeleNumRefBatch +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + public $prefix = 'SN'; + + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'Serial number'; + + + /** + * Return description of numbering module + * + * @return string Text with description + */ + public function info() + { + global $langs; + return $langs->trans("SimpleNumRefModelDesc", $this->prefix); + } + + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample() + { + return $this->prefix."0501-0001"; + } + + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @return boolean false if conflict, true if ok + */ + public function canBeActivated() + { + global $conf, $langs, $db; + + $coyymm = ''; $max = ''; + + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."product_lot"; + $sql .= " WHERE ref LIKE '".$db->escape($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)) + { + $langs->load("errors"); + $this->error = $langs->trans('ErrorNumRefModel', $max); + return false; + } + + return true; + } + + /** + * Return next free value + * + * @param Product $objprod Object product + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + */ + public function getNextValue($objprod, $object) + { + global $db, $conf; + + // First, we get the max value + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."product_lot"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + $sql .= " AND entity = ".$conf->entity; + + $resql = $db->query($sql); + if ($resql) + { + $obj = $db->fetch_object($resql); + if ($obj) $max = intval($obj->max); + else $max = 0; + } + else + { + dol_syslog("mod_mo_standard::getNextValue", LOG_DEBUG); + return -1; + } + + //$date=time(); + $date = $object->date_creation; + $yymm = strftime("%y%m", $date); + + if ($max >= (pow(10, 4) - 1)) $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is + else $num = sprintf("%04s", $max + 1); + + dol_syslog("mod_mo_standard::getNextValue return ".$this->prefix.$yymm."-".$num); + return $this->prefix.$yymm."-".$num; + } +} diff --git a/htdocs/core/modules/product_batch/modules_product_batch.class.php b/htdocs/core/modules/product_batch/modules_product_batch.class.php index f5ef6ac3dda..7cd189f96d6 100644 --- a/htdocs/core/modules/product_batch/modules_product_batch.class.php +++ b/htdocs/core/modules/product_batch/modules_product_batch.class.php @@ -65,3 +65,89 @@ abstract class ModelePDFProductBatch extends CommonDocGenerator return $list; } } + +/** + * Parent class to manage numbering of batch products + */ +abstract class ModeleNumRefBatch +{ + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * Return if a module can be used or not + * + * @return boolean true if module can be used + */ + public function isEnabled() + { + return true; + } + + /** + * Returns the default description of the numbering template + * + * @return string Texte descripif + */ + public function info() + { + global $langs; + $langs->load("productbatch"); + return $langs->trans("NoDescription"); + } + + /** + * Returns an example of numbering + * + * @return string Example + */ + public function getExample() + { + global $langs; + $langs->load("productbatch"); + return $langs->trans("NoExample"); + } + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @return boolean false if conflict, true if ok + */ + public function canBeActivated() + { + return true; + } + + /** + * Returns next assigned value + * + * @param Societe $objsoc Object thirdparty + * @param Object $object Object we need next value for + * @return string Valeur + */ + public function getNextValue($objsoc, $object) + { + global $langs; + return $langs->trans("NotAvailable"); + } + + /** + * Returns version of numbering module + * + * @return string Valeur + */ + public 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; + if ($this->version) return $this->version; + return $langs->trans("NotAvailable"); + } +} \ No newline at end of file diff --git a/htdocs/product/admin/product_lot.php b/htdocs/product/admin/product_lot.php new file mode 100644 index 00000000000..04c089a0528 --- /dev/null +++ b/htdocs/product/admin/product_lot.php @@ -0,0 +1,192 @@ + + * + * 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 . + */ + +/** + * \file htdocs/product/admin/product_lot.php + * \ingroup produit + * \brief Setup page of product lot module + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array("admin", "products", "productbatch")); + +// Security check +if (!$user->admin || (empty($conf->productbatch->enabled))) + accessforbidden(); + +$action = GETPOST('action', 'alpha'); +$value = GETPOST('value', 'alpha'); + +/* + * Actions + */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + +if ($action == 'updateMask') +{ + $maskconstbatch = GETPOST('maskconstBatch', 'alpha'); + $maskbatch = GETPOST('maskMo', 'alpha'); + + if ($maskconstbatch) $res = dolibarr_set_const($db, $maskconstbatch, $maskbatch, 'chaine', 0, '', $conf->entity); + + if (!$res > 0) $error++; + + if (!$error) + { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } + else + { + setEventMessages($langs->trans("Error"), null, 'errors'); + } +} + +elseif ($action == 'setmod') +{ + // TODO Check if numbering module chosen can be activated + // by calling method canBeActivated + + dolibarr_set_const($db, "BATCH_ADDON", $value, 'chaine', 0, '', $conf->entity); +} + + +/* + * View + */ + +$form = new Form($db); + +$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + +llxHeader("", $langs->trans("ProductLotSetup")); + +$linkback = ''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans("ProductLotSetup"), $linkback, 'title_setup'); + +$head = product_lot_admin_prepare_head(); + +dol_fiche_head($head, 'settings', $langs->trans("Batch"), -1, 'productbatch'); + +/* + * MOs Numbering model + */ + +print load_fiche_titre($langs->trans("BatchNumberingModules"), '', ''); + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''."\n"; + +clearstatcache(); + +foreach ($dirmodels as $reldir) +{ + $dir = dol_buildpath($reldir."core/modules/product_batch/"); + + if (is_dir($dir)) + { + $handle = opendir($dir); + if (is_resource($handle)) + { + while (($file = readdir($handle)) !== false) + { + if (substr($file, 0, 10) == 'mod_batch_' && substr($file, dol_strlen($file) - 3, 3) == 'php') + { + $file = substr($file, 0, dol_strlen($file) - 4); + + require_once $dir.$file.'.php'; + + $module = new $file($db); + + // 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()) + { + print ''; + + // Show example of numbering model + print ''."\n"; + + print ''; + + $batch = new Productlot($db); + $batch->initAsSpecimen(); + + // Info + $htmltooltip = ''; + $htmltooltip .= ''.$langs->trans("Version").': '.$module->getVersion().'
'; + $nextval = $module->getNextValue($mysoc, $batch); + if ("$nextval" != $langs->trans("NotAvailable")) { // Keep " on nextval + $htmltooltip .= ''.$langs->trans("NextValue").': '; + if ($nextval) { + if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured') + $nextval = $langs->trans($nextval); + $htmltooltip .= $nextval.'
'; + } else { + $htmltooltip .= $langs->trans($module->error).'
'; + } + } + + print ''; + + print "\n"; + } + } + } + closedir($handle); + } + } +} + +print "
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Example").''.$langs->trans("Status").''.$langs->trans("ShortInfo").'
'.$module->name."\n"; + print $module->info(); + print ''; + $tmp = $module->getExample(); + if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; + elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + else print $tmp; + print '
'; + if ($conf->global->BATCH_ADDON == $file) + { + print img_picto($langs->trans("Activated"), 'switch_on'); + } + else + { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print '

\n"; + +// End of page +llxFooter(); +$db->close();