From 1c5888d6d27c8608a701b46d106efa09ba4a19ea Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Wed, 23 Nov 2022 20:47:32 +0100 Subject: [PATCH 01/12] add hook 'llxFooter' --- htdocs/core/class/hookmanager.class.php | 1 + htdocs/main.inc.php | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 5f87d81db9d..4886a3fd5d0 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -195,6 +195,7 @@ class HookManager 'getFormatedSupplierRef', 'getIdProfUrl', 'getInputIdProf', + 'llxFooter', 'menuDropdownQuickaddItems', 'menuLeftMenuItems', 'moveUploadedFile', diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 4b580e7b808..e0ea7b1dbfc 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -3213,6 +3213,17 @@ if (!function_exists("llxFooter")) { $ext = 'layout='.$conf->browser->layout.'&version='.urlencode(DOL_VERSION); + // Hook to add more things on all pages within fiche DIV + $llxfooter = ''; + $parameters = array(); + $reshook = $hookmanager->executeHooks('llxFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $llxfooter .= $hookmanager->resPrint; + } elseif ($reshook > 0) { + $llxfooter = $hookmanager->resPrint; + } + print $llxfooter; + // Global html output events ($mesgs, $errors, $warnings) dol_htmloutput_events($disabledoutputofmessages); From c033a4778e68f8371ff7a4983a0751de0ed6b591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Llu=C3=ADs?= Date: Wed, 21 Dec 2022 13:17:18 +0100 Subject: [PATCH 02/12] New filter for Signed+Billed in proposals New filter for Signed+Billed in proposals --- htdocs/core/class/html.formpropal.class.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index e23e71a8124..d9c458161bc 100644 --- a/htdocs/core/class/html.formpropal.class.php +++ b/htdocs/core/class/html.formpropal.class.php @@ -132,6 +132,14 @@ class FormPropal print ''; $i++; } + //Option for Signed+Billed + if ($selected != '' && $selected == "2,4") { + print ''; print ''; print ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($showempty < 0 ? (string) $showempty : '-1'), $morecss); From 3004c3cd920b815651aaa36c491cd4444d7fb1e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Llu=C3=ADs?= Date: Wed, 21 Dec 2022 13:22:56 +0100 Subject: [PATCH 03/12] Update html.formpropal.class.php --- htdocs/core/class/html.formpropal.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index d9c458161bc..48551926e1f 100644 --- a/htdocs/core/class/html.formpropal.class.php +++ b/htdocs/core/class/html.formpropal.class.php @@ -1,5 +1,6 @@ + * Copyright (C) 2022 Josep LluĂ­s Amador * * 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 From 80d6c262029ec69caec69db358fa4fbae5cc89ec Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 21 Dec 2022 12:31:33 +0000 Subject: [PATCH 04/12] Fixing style errors. --- htdocs/core/class/html.formpropal.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index 48551926e1f..fbbf2c97fb7 100644 --- a/htdocs/core/class/html.formpropal.class.php +++ b/htdocs/core/class/html.formpropal.class.php @@ -135,12 +135,12 @@ class FormPropal } //Option for Signed+Billed if ($selected != '' && $selected == "2,4") { - print ''; + print ''; print ''; print ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($showempty < 0 ? (string) $showempty : '-1'), $morecss); From aa5419cfb53626010970a5a6339bd33e298cb6a2 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Thu, 29 Dec 2022 16:10:53 +0100 Subject: [PATCH 05/12] update in modulbuilder for menu object --- htdocs/modulebuilder/index.php | 58 +++++++++++++++++-- .../core/modules/modMyModule.class.php | 2 +- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 8b87d84c10e..eeb016db6b6 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -1344,12 +1344,12 @@ if ($dirins && $action == 'initobject' && $module && $objectname) { // 0=Menu for internal users, 1=external users, 2=both 'user'=>2 );\n"; - $stringtoadd = preg_replace('/MyObject/', $objectnameloop, $stringtoadd); + $stringtoadd = preg_replace('/MyObject/', $objectname, $stringtoadd); $stringtoadd = preg_replace('/mymodule/', strtolower($module), $stringtoadd); - $stringtoadd = preg_replace('/myobject/', strtolower($objectnameloop), $stringtoadd); + $stringtoadd = preg_replace('/myobject/', strtolower($objectname), $stringtoadd); $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php'; - + } // TODO Allow a replace with regex using dolReplaceInFile with param arryreplacementisregex to 1 // TODO Avoid duplicate addition @@ -1357,7 +1357,6 @@ if ($dirins && $action == 'initobject' && $module && $objectname) { // Add module descriptor to list of files to replace "MyObject' string with real name of object. $filetogenerate[] = 'core/modules/mod'.$module.'.class.php'; - } } if (!$error) { @@ -1377,7 +1376,7 @@ if ($dirins && $action == 'initobject' && $module && $objectname) { 'htdocs/modulebuilder/template/'=>strtolower($modulename), 'myobject'=>strtolower($objectname), 'MyObject'=>$objectname, - 'MYOBJECT'=>strtoupper($objectname), + //'MYOBJECT'=>strtoupper($objectname), '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '') ); @@ -1730,6 +1729,55 @@ if ($dirins && $action == 'confirm_deleteobject' && $objectname) { 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php'=>'core/modules/'.strtolower($module).'/doc/pdf_standard_'.strtolower($objectname).'.modules.php' ); + //menu for the object selected + $stringtoedit = "\$this->menu[\$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=".strtolower($module)."', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'List ".ucfirst($objectname)."', + 'mainmenu'=>'".strtolower($module)."', + 'leftmenu'=>'".strtolower($module)."_".strtolower($objectname)."', + 'url'=>'/".strtolower($module)."/".strtolower($objectname)."_list.php', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'".strtolower($module)."@".strtolower($module)."', + 'position'=>1100+\$r, + // Define condition to show or hide menu entry. Use '\$conf->".strtolower($module)."->enabled' if entry must be visible if module is enabled. Use '\$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'\$conf->".strtolower($module)."->enabled', + // Use 'perms'=>'\$user->rights->".strtolower($module)."->level1->level2' if you want your menu with a permission rules + 'perms'=>'1', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2, + ); + \$this->menu[\$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=".strtolower($module).",fk_leftmenu=".strtolower($module)."_".strtolower($objectname)."', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'New ".ucfirst($objectname)."', + 'mainmenu'=>'".strtolower($module)."', + 'leftmenu'=>'".strtolower($module)."_".strtolower($objectname)."', + 'url'=>'/".strtolower($module)."/".strtolower($objectname)."_card.php?action=create', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'".strtolower($module)."@".strtolower($module)."', + 'position'=>1100+\$r, + // Define condition to show or hide menu entry. Use '\$conf->".strtolower($module)."->enabled' if entry must be visible if module is enabled. Use '\$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'\$conf->".strtolower($module)."->enabled', + // Use 'perms'=>'\$user->rights->".strtolower($module)."->level1->level2' if you want your menu with a permission rules + 'perms'=>'1', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2 + );"; + + $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; + + $check = dolReplaceInFile($moduledescriptorfile, array($stringtoedit => '')); + if ($check > 0) { + dolReplaceInFile($moduledescriptorfile, array('/*'.strtoupper($objectname).'*/' => '')); + } + $resultko = 0; foreach ($filetodelete as $filetodelete) { $resulttmp = dol_delete_file($dir.'/'.$filetodelete, 0, 0, 1); diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index 99cd900b512..2788c78fc37 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -348,7 +348,7 @@ class modMyModule extends DolibarrModules 'target'=>'', 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both ); - END MODULEBUILDER LEFTMENU MYOBJECT */ + /* END MODULEBUILDER LEFTMENU MYOBJECT */ // Exports profiles provided by this module $r = 1; /* BEGIN MODULEBUILDER EXPORT MYOBJECT */ From e80425ec75d11f76abbc09c2f67cf98a89ca4b94 Mon Sep 17 00:00:00 2001 From: Je2fb <46494485+Je2fb@users.noreply.github.com> Date: Fri, 30 Dec 2022 16:07:10 +0100 Subject: [PATCH 06/12] Fix issue #23345 --- htdocs/expedition/class/api_shipments.class.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/htdocs/expedition/class/api_shipments.class.php b/htdocs/expedition/class/api_shipments.class.php index 357683ef35a..0536215d57c 100644 --- a/htdocs/expedition/class/api_shipments.class.php +++ b/htdocs/expedition/class/api_shipments.class.php @@ -686,6 +686,11 @@ class Shipments extends DolibarrApi if (!empty($object->lines) && is_array($object->lines)) { foreach ($object->lines as $line) { + if (is_array($line->detail_batch)) { + foreach($line->detail_batch as $keytmp2 => $valtmp2) { + unset($line->detail_batch[$keytmp2]->db); + } + } unset($line->tva_tx); unset($line->vat_src_code); unset($line->total_ht); From 8196cfac8a5baa551b8e828dc10ae6799e058962 Mon Sep 17 00:00:00 2001 From: Je2fb <46494485+Je2fb@users.noreply.github.com> Date: Fri, 30 Dec 2022 16:13:38 +0100 Subject: [PATCH 07/12] Create api_multicurrencies.class.php Add API for retrieves curriences information with the last rate --- .../class/api_multicurrencies.class.php | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 htdocs/multicurrency/class/api_multicurrencies.class.php diff --git a/htdocs/multicurrency/class/api_multicurrencies.class.php b/htdocs/multicurrency/class/api_multicurrencies.class.php new file mode 100644 index 00000000000..2ef1ba519b4 --- /dev/null +++ b/htdocs/multicurrency/class/api_multicurrencies.class.php @@ -0,0 +1,126 @@ + + * + * 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 . + */ + +use Luracast\Restler\RestException; + +//require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/multicurrency.lib.php'; + +/** + * API class for MultiCurrency + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class MultiCurrencies extends DolibarrApi +{ + + /** + * Constructor + */ + public function __construct() + { + global $db, $conf; + $this->db = $db; + } + + /** + * Get a list of currencies + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.product_id:=:1) and (t.date_creation:<:'20160101')" + * @return array Array of warehouse objects + * + * @throws RestException + */ + public function index($sortfield = "t.rowid", $sortorder = 'ASC', $sqlfilters = '') + { + global $db, $conf; + + $obj_ret = array(); + + $sql = "SELECT t.rowid"; + $sql .= " FROM ".$this->db->prefix()."multicurrency as t"; + $sql .= ' WHERE 1 = 1'; + // Add sql filters + if ($sqlfilters) { + $errormessage = ''; + if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { + throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + } + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; + $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql .= $this->db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) { + $page = 0; + } + $offset = $limit * $page; + + $sql .= $this->db->plimit($limit + 1, $offset); + } + + $result = $this->db->query($sql); + if ($result) { + $i = 0; + $num = $this->db->num_rows($result); + $min = min($num, ($limit <= 0 ? $num : $limit)); + while ($i < $min) { + $obj = $this->db->fetch_object($result); + $multicurrency_static = new MultiCurrency($this->db); + if ($multicurrency_static->fetch($obj->rowid)) { + $obj_ret[] = $this->_cleanObjectDatas($multicurrency_static); + } + $i++; + } + } else { + throw new RestException(503, 'Error when retrieve currencies list : '.$this->db->lasterror()); + } + if (!count($obj_ret)) { + throw new RestException(404, 'No currencies found'); + } + + return $obj_ret; + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Clean sensible object datas + * + * @param MultiCurrency $object Object to clean + * @return Object Object with cleaned properties + */ + protected function _cleanObjectDatas($object) + { + // phpcs:enable + $object = parent::_cleanObjectDatas($object); + + // Clear all fields out of interrest + foreach($object as $key => $value){ + if ($key == "rate") $object->$key = $this->_cleanObjectDatas($object->$key); + if ($key == "id" || $key == "code" || $key == "rate" || $key == "date_sync") + continue; + unset($object->$key); + } + + return $object; + } + +} From ab0e069ae16c53c4b6cdd01c64a37cf9197a7a20 Mon Sep 17 00:00:00 2001 From: Je2fb <46494485+Je2fb@users.noreply.github.com> Date: Fri, 30 Dec 2022 16:16:29 +0100 Subject: [PATCH 08/12] Update functions2.lib.php Add the moduledirforclass "multicurrency" to add a API to get the currencies --- htdocs/core/lib/functions2.lib.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php index 05ed388d41f..692d01f9ef0 100644 --- a/htdocs/core/lib/functions2.lib.php +++ b/htdocs/core/lib/functions2.lib.php @@ -2652,6 +2652,8 @@ function getModuleDirForApiClass($moduleobject) $moduledirforclass = 'commande'; } elseif ($moduleobject == 'shipments') { $moduledirforclass = 'expedition'; + } elseif ($moduleobject == 'multicurrencies') { + $moduledirforclass = 'multicurrency'; } elseif ($moduleobject == 'facture' || $moduleobject == 'invoice' || $moduleobject == 'invoices') { $moduledirforclass = 'compta/facture'; } elseif ($moduleobject == 'project' || $moduleobject == 'projects' || $moduleobject == 'task' || $moduleobject == 'tasks') { From 8a2f44aec485cd4e817c27c083fdc709b0f0b548 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Fri, 30 Dec 2022 15:20:12 +0000 Subject: [PATCH 09/12] Fixing style errors. --- .../expedition/class/api_shipments.class.php | 8 ++++---- .../class/api_multicurrencies.class.php | 19 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/htdocs/expedition/class/api_shipments.class.php b/htdocs/expedition/class/api_shipments.class.php index 0536215d57c..450fe943d7e 100644 --- a/htdocs/expedition/class/api_shipments.class.php +++ b/htdocs/expedition/class/api_shipments.class.php @@ -687,10 +687,10 @@ class Shipments extends DolibarrApi if (!empty($object->lines) && is_array($object->lines)) { foreach ($object->lines as $line) { if (is_array($line->detail_batch)) { - foreach($line->detail_batch as $keytmp2 => $valtmp2) { - unset($line->detail_batch[$keytmp2]->db); - } - } + foreach ($line->detail_batch as $keytmp2 => $valtmp2) { + unset($line->detail_batch[$keytmp2]->db); + } + } unset($line->tva_tx); unset($line->vat_src_code); unset($line->total_ht); diff --git a/htdocs/multicurrency/class/api_multicurrencies.class.php b/htdocs/multicurrency/class/api_multicurrencies.class.php index 2ef1ba519b4..e88f936c571 100644 --- a/htdocs/multicurrency/class/api_multicurrencies.class.php +++ b/htdocs/multicurrency/class/api_multicurrencies.class.php @@ -96,7 +96,7 @@ class MultiCurrencies extends DolibarrApi if (!count($obj_ret)) { throw new RestException(404, 'No currencies found'); } - + return $obj_ret; } @@ -111,16 +111,15 @@ class MultiCurrencies extends DolibarrApi { // phpcs:enable $object = parent::_cleanObjectDatas($object); - - // Clear all fields out of interrest - foreach($object as $key => $value){ - if ($key == "rate") $object->$key = $this->_cleanObjectDatas($object->$key); - if ($key == "id" || $key == "code" || $key == "rate" || $key == "date_sync") - continue; - unset($object->$key); + + // Clear all fields out of interrest + foreach ($object as $key => $value) { + if ($key == "rate") $object->$key = $this->_cleanObjectDatas($object->$key); + if ($key == "id" || $key == "code" || $key == "rate" || $key == "date_sync") + continue; + unset($object->$key); } - + return $object; } - } From da4567c87524c96337cfa89588dfe3a689ac7c2a Mon Sep 17 00:00:00 2001 From: Christian Humpel Date: Sun, 1 Jan 2023 15:05:04 +0100 Subject: [PATCH 10/12] Set $remise_percent to 0, if GETPOST is empty. --- htdocs/commande/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 77a59c159ff..996beecab61 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1106,7 +1106,7 @@ if (empty($reshook)) { $special_code = 3; } - $remise_percent = price2num(GETPOST('remise_percent'), '', 2); + $remise_percent = GETPOST('remise_percent') != '' ? price2num(GETPOST('remise_percent'), '', 2) : 0; // Check minimum price $productid = GETPOST('productid', 'int'); From edfa7dddfcc4c78faa6f6130f418be6818488205 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 01:50:25 +0100 Subject: [PATCH 11/12] Update html.formpropal.class.php --- htdocs/core/class/html.formpropal.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index fbbf2c97fb7..7cce3c839c5 100644 --- a/htdocs/core/class/html.formpropal.class.php +++ b/htdocs/core/class/html.formpropal.class.php @@ -139,7 +139,7 @@ class FormPropal } else { print ''; print ''; From 9aecf48ce33880623e3f5f0330cbbba76710bd7d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 01:53:05 +0100 Subject: [PATCH 12/12] Update main.inc.php --- htdocs/main.inc.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index e0ea7b1dbfc..dbb18aa61d3 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -3211,7 +3211,7 @@ if (!function_exists("llxFooter")) { global $contextpage, $page, $limit, $mode; global $dolibarr_distrib; - $ext = 'layout='.$conf->browser->layout.'&version='.urlencode(DOL_VERSION); + $ext = 'layout='.urlencode($conf->browser->layout).'&version='.urlencode(DOL_VERSION); // Hook to add more things on all pages within fiche DIV $llxfooter = ''; @@ -3222,7 +3222,9 @@ if (!function_exists("llxFooter")) { } elseif ($reshook > 0) { $llxfooter = $hookmanager->resPrint; } - print $llxfooter; + if ($llxfooter) { + print $llxfooter; + } // Global html output events ($mesgs, $errors, $warnings) dol_htmloutput_events($disabledoutputofmessages);