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'); diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 71a92ebb6b1..0659240c8c7 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -198,6 +198,7 @@ class HookManager 'getIdProfUrl', 'getInputIdProf', 'isPaymentOK', + 'llxFooter', 'menuDropdownQuickaddItems', 'menuLeftMenuItems', 'moveUploadedFile', diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index e23e71a8124..7cce3c839c5 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 @@ -132,6 +133,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); 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') { diff --git a/htdocs/expedition/class/api_shipments.class.php b/htdocs/expedition/class/api_shipments.class.php index 357683ef35a..450fe943d7e 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); diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index caed0fc2a7f..d8eb602f624 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -3240,7 +3240,20 @@ 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 = ''; + $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; + } + if ($llxfooter) { + print $llxfooter; + } // Global html output events ($mesgs, $errors, $warnings) dol_htmloutput_events($disabledoutputofmessages); diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 7c83987b6ed..97e494a8a2e 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 $tmpfiletodelete) { $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete, 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 */ diff --git a/htdocs/multicurrency/class/api_multicurrencies.class.php b/htdocs/multicurrency/class/api_multicurrencies.class.php new file mode 100644 index 00000000000..e88f936c571 --- /dev/null +++ b/htdocs/multicurrency/class/api_multicurrencies.class.php @@ -0,0 +1,125 @@ + + * + * 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; + } +}