* Copyright (C) 2004-2018 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2012-2016 Marcos García * Copyright (C) 2013-2019 Juanjo Menent * Copyright (C) 2013-2015 Raphaël Doursenaud * Copyright (C) 2013 Jean Heimburger * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2013 Florian Henry * Copyright (C) 2013 Adolfo segura * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2016 Ferran Marcet * Copyright (C) 2023 Lenin Rivas * Copyright (C) 2024 MDW * Copyright (C) 2024 Frédéric France * * 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/multicurrency/multicurrency_rate.php * \ingroup multicurrency * \brief Page to list multicurrency rate */ // Load Dolibarr environment require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/multicurrency.lib.php'; // Load translation files required by the page $langs->loadLangs(array('admin', 'multicurrency')); // Get Parameters $action = GETPOST('action', 'alpha'); $massaction = GETPOST('massaction', 'alpha'); $show_files = GETPOSTINT('show_files'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $id_rate_selected = GETPOSTINT('id_rate'); $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $search_date_sync = dol_mktime(0, 0, 0, GETPOSTINT('search_date_syncmonth'), GETPOSTINT('search_date_syncday'), GETPOSTINT('search_date_syncyear')); $search_date_sync_end = dol_mktime(0, 0, 0, GETPOSTINT('search_date_sync_endmonth'), GETPOSTINT('search_date_sync_endday'), GETPOSTINT('search_date_sync_endyear')); $search_rate = GETPOST('search_rate', 'alpha'); $search_rate_indirect = GETPOST('search_rate_indirect', 'alpha'); $search_code = GETPOST('search_code', 'alpha'); $multicurrency_code = GETPOST('multicurrency_code', 'alpha'); $dateinput = dol_mktime(0, 0, 0, GETPOSTINT('dateinputmonth'), GETPOSTINT('dateinputday'), GETPOSTINT('dateinputyear')); $rateinput = (float) price2num(GETPOST('rateinput', 'alpha')); $rateindirectinput = (float) price2num(GETPOST('rateinidirectinput', 'alpha')); $optioncss = GETPOST('optioncss', 'alpha'); $limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit; $page = GETPOSTINT("page"); if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); if (!$sortfield) { $sortfield = "cr.date_sync"; } if (!$sortorder) { $sortorder = "DESC"; } $type = ''; $texte = ''; $newcardbutton = ''; // Initialize a technical objects $object = new CurrencyRate($db); $form = new Form($db); $extrafields = new ExtraFields($db); // Initialize a technical object to manage hooks. Note that conf->hooks_modules contains array of hooks $hookmanager->initHooks(array('EditorRatelist', 'globallist')); if (empty($action)) { $action = 'list'; } // List of fields to search into when doing a "search in all" $fieldstosearchall = array( 'cr.date_sync' => "date_sync", 'cr.rate' => "rate", 'cr.rate_indirect' => "rate_indirect", 'm.code' => "code", ); // Definition of fields for lists $arrayfields = array( 'cr.date_sync' => array('label' => 'Date', 'checked' => 1), 'cr.rate' => array('label' => 'Rate', 'checked' => 1), 'cr.rate_indirect' => array('label' => 'RateIndirect', 'checked' => 0, 'enabled' => (!getDolGlobalString('MULTICURRENCY_USE_RATE_INDIRECT') ? 0 : 1)), 'm.code' => array('label' => 'Code', 'checked' => 1), ); $object->fields = dol_sort_array($object->fields, 'position'); $arrayfields = dol_sort_array($arrayfields, 'position'); '@phan-var-force array,position?:int,help?:string}> $arrayfields'; // dol_sort_array looses type for Phan // Access control // TODO Open this page to a given permission so a sale representative can modify change rates. Permission should be added into module multicurrency. // One permission to read rates (history) and one to add/edit rates. if (!$user->admin || !isModEnabled("multicurrency")) { accessforbidden(); } $error = 0; /* * Actions */ if ($action == "create" && $user->hasRight('multicurrency', 'currency', 'read')) { if (empty($multicurrency_code) || $multicurrency_code == '-1') { setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Currency")), null, "errors"); $error++; } if ($rateinput == 0) { setEventMessages($langs->trans('NoEmptyRate'), null, "errors"); $error++; } elseif (empty($rateinput)) { setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Rate")), null, "errors"); $error++; } if (!$error) { $currencyRate_static = new CurrencyRate($db); $currency_static = new MultiCurrency($db); $fk_currency = $currency_static->getIdFromCode($db, $multicurrency_code); $currencyRate_static->fk_multicurrency = $fk_currency; $currencyRate_static->entity = $conf->entity; $currencyRate_static->date_sync = $dateinput; $currencyRate_static->rate = $rateinput; $currencyRate_static->rate_indirect = $rateindirectinput; $result = $currencyRate_static->create($user, intval($fk_currency)); if ($result > 0) { setEventMessages($langs->trans('successRateCreate', $multicurrency_code), null); } else { dol_syslog("currencyRate:createRate", LOG_WARNING); setEventMessages($currencyRate_static->error, $currencyRate_static->errors, 'errors'); } } } if ($action == 'update' && $user->hasRight('multicurrency', 'currency', 'read')) { $currencyRate = new CurrencyRate($db); $result = $currencyRate->fetch($id_rate_selected); if ($result > 0) { $currency_static = new MultiCurrency($db); $fk_currency = $currency_static->getIdFromCode($db, $multicurrency_code); $currencyRate->date_sync = $dateinput; $currencyRate->fk_multicurrency = $fk_currency; $currencyRate->rate = $rateinput; $res = $currencyRate->update($user); if ($res) { setEventMessages($langs->trans('successUpdateRate'), null); } else { setEventMessages($currencyRate->error, $currencyRate->errors, "errors"); } } else { setEventMessages($langs->trans('Error'), null, "warnings"); } } if ($action == "deleteRate" && $user->hasRight('multicurrency', 'currency', 'read')) { $current_rate = new CurrencyRate($db); $current_rate->fetch((int) $id_rate_selected); if ($current_rate) { $current_currency = new MultiCurrency($db); $current_currency->fetch($current_rate->fk_multicurrency); if ($current_currency) { $delayedhtmlcontent = $form->formconfirm( $_SERVER["PHP_SELF"].'?id_rate='.$id_rate_selected, $langs->trans('DeleteLineRate'), $langs->trans('ConfirmDeleteLineRate', $current_rate->rate, $current_currency->name, $current_rate->date_sync), 'confirm_delete', '', 0, 1 ); } else { dol_syslog("Multicurrency::fetch", LOG_WARNING); } } else { setEventMessage($langs->trans('NoCurrencyRateSelected'), "warnings"); } } if ($action == "confirm_delete" && $user->hasRight('multicurrency', 'currency', 'read')) { $current_rate = new CurrencyRate($db); $current_rate->fetch((int) $id_rate_selected); if ($current_rate) { $result = $current_rate->delete($user); if ($result) { setEventMessages($langs->trans('successRateDelete'), null); } else { setEventMessages($current_rate->error, $current_rate->errors, 'errors'); } } else { setEventMessages($langs->trans('NoCurrencyRateSelected'), null, "warnings"); dol_syslog($langs->trans('NoCurrencyRateSelected'), LOG_WARNING); } } if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } $parameters = array(); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); } if (empty($reshook)) { // Selection of new fields include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; // Purge search criteria if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers $sall = ""; $search_date_sync = ""; $search_date_sync_end = ""; $search_rate = ""; $search_code = ""; $search_array_options = array(); } // Mass actions $objectclass = "CurrencyRate"; $uploaddir = $conf->multicurrency->multidir_output; // define only because core/actions_massactions.inc.php want it $permissiontoread = $user->admin; $permissiontodelete = $user->admin; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; } /* * View */ $form = new Form($db); $title = $langs->trans("CurrencyRate"); $page_name = "MultiCurrencySetup"; $help_url = ''; llxHeader('', $title, $help_url, ''); // Subheader $linkback = ''.$langs->trans("BackToModuleList").''; print load_fiche_titre($langs->trans($page_name), $linkback); // Configuration header $head = multicurrencyAdminPrepareHead(); print dol_get_fiche_head($head, 'ratelist', $langs->trans("ModuleSetup"), -1, "multicurrency"); // ACTION if (!in_array($action, array("updateRate", "deleteRate"))) { print '
'; print ''; print '
'; print ''; print ' '; print ' '; print ''; print ''; print ' '; print ' '; if (getDolGlobalString('MULTICURRENCY_USE_RATE_INDIRECT')) { print ' '; print ' '; // LRR Calculate Rate Direct print ''; } print ''; print '
'.$langs->trans('Date').''; print $form->selectDate($dateinput, 'dateinput', 0, 0, 1, '', 1, 1); print ' '.$langs->trans('Currency').''.$form->selectMultiCurrency((GETPOSTISSET('multicurrency_code') ? GETPOST('multicurrency_code', 'alpha') : $multicurrency_code), 'multicurrency_code', 1, " code != '".$db->escape($conf->currency)."'", true).''.$langs->trans('Rate').' / '.$langs->getCurrencySymbol($conf->currency).''.$langs->trans('RateIndirect').' / '.$langs->getCurrencySymbol($conf->currency).''; print ''; print ''; print '
'; print '
'; print '
'; print '
'; } $sql = 'SELECT cr.rowid, cr.date_sync, cr.rate, cr.rate_indirect, cr.entity, m.code, m.name'; // Add fields from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; $sql .= ' FROM '.MAIN_DB_PREFIX.'multicurrency_rate as cr '; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."multicurrency AS m ON cr.fk_multicurrency = m.rowid"; if ($sall) { $sql .= natural_search(array_keys($fieldstosearchall), $sall); } if ($search_date_sync && $search_date_sync_end) { $sql .= " AND (cr.date_sync BETWEEN '".$db->idate($search_date_sync)."' AND '".$db->idate($search_date_sync_end)."')"; } elseif ($search_date_sync && !$search_date_sync_end) { $sql .= natural_search('cr.date_sync', $db->idate($search_date_sync)); } if ($search_rate) { $sql .= natural_search('cr.rate', $search_rate, 1); } if ($search_code) { $sql .= natural_search('m.code', $search_code); } $sql .= " WHERE m.code <> '".$db->escape($conf->currency)."'"; // Add where from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; $sql .= " GROUP BY cr.rowid, cr.date_sync, cr.rate, cr.rate_indirect, m.code, cr.entity, m.code, m.name"; // Add fields from hooks $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldSelect', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; $sql .= $db->order($sortfield, $sortorder); $nbtotalofrecords = ''; if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { $result = $db->query($sql); if ($result) { $nbtotalofrecords = $db->num_rows($result); if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 $page = 0; $offset = 0; } } else { setEventMessage($langs->trans('No_record_on_multicurrency_rate'), 'warnings'); } } $sql .= $db->plimit($limit + 1, $offset); $resql = $db->query($sql); if ($resql) { $num = $db->num_rows($resql); $arrayofselected = is_array($toselect) ? $toselect : array(); $param = ''; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.((int) $limit); } if ($sall) { $param .= "&sall=".urlencode($sall); } if ($search_date_sync) { $param = "&search_date_sync=".$search_date_sync; } if ($search_date_sync_end) { $param = "&search_date_sync_end=".$search_date_sync_end; } if ($search_rate) { $param = "&search_rate=".urlencode($search_rate); } if ($search_code != '') { $param .= "&search_code=".urlencode($search_code); } // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; if ($user->admin) { $arrayofmassactions['predelete'] = $langs->trans("Delete"); } if (in_array($massaction, array('presend', 'predelete'))) { $arrayofmassactions = array(); } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); print '
'; if ($optioncss != '') { print ''; } print ''; print ''; print ''; print ''; print ''; print ''; print ''; print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_currency.png', 0, $newcardbutton, '', $limit); include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; if ($sall) { foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); } print '
'.$langs->trans("FilterOnInto", $sall).implode(', ', $fieldstosearchall).'
'; } // Filter on categories $moreforfilter = ''; $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $moreforfilter .= $hookmanager->resPrint; } else { $moreforfilter = $hookmanager->resPrint; } if ($moreforfilter) { print '
'; print $moreforfilter; print '
'; } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields if ($massactionbutton) { $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); } print '
'; print ''."\n"; // Lines with input filters print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; } // date if (!empty($arrayfields['cr.date_sync']['checked'])) { print ''; } // code if (!empty($arrayfields['m.code']['checked'])) { print ''; } // rate if (!empty($arrayfields['cr.rate']['checked'])) { print ''; } // Fields from hook $parameters = array('arrayfields' => $arrayfields); $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; } print ''; print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'maxwidthsearch center '); } if (!empty($arrayfields['cr.date_sync']['checked'])) { print_liste_field_titre($arrayfields['cr.date_sync']['label'], $_SERVER["PHP_SELF"], "cr.date_sync", "", $param, "", $sortfield, $sortorder); } if (!empty($arrayfields['m.code']['checked'])) { print_liste_field_titre($arrayfields['m.code']['label'], $_SERVER["PHP_SELF"], "m.code", "", $param, "", $sortfield, $sortorder); } if (!empty($arrayfields['cr.rate']['checked'])) { print_liste_field_titre($arrayfields['cr.rate']['label'], $_SERVER["PHP_SELF"], "cr.rate", "", $param, "", $sortfield, $sortorder); } // Hook fields $parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder); $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch center '); } print "\n"; $i = 0; $totalarray = array(); $totalarray['nbfield'] = 0; while ($i < min($num, $limit)) { $obj = $db->fetch_object($resql); print ''; // USER REQUEST UPDATE FOR THIS LINE if ($action == "updateRate" && $obj->rowid == $id_rate_selected) { if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; } print ''; print ''; print ''; if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; } } else { // Action if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; if (!$i) { $totalarray['nbfield']++; } } // date_sync if (!empty($arrayfields['cr.date_sync']['checked'])) { print '\n"; if (!$i) { $totalarray['nbfield']++; } } // code if (!empty($arrayfields['m.code']['checked'])) { print '\n"; if (! $i) { $totalarray['nbfield']++; } } // rate if (!empty($arrayfields['cr.rate']['checked'])) { print '\n"; if (! $i) { $totalarray['nbfield']++; } } // rate indirect if (!empty($arrayfields['cr.rate_indirect']['checked'])) { print '\n"; if (! $i) { $totalarray['nbfield']++; } } // Fields from hook $parameters = array('arrayfields' => $arrayfields, 'obj' => $obj); $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; if (!$i) { $totalarray['nbfield']++; } } print "\n"; $i++; } } $db->free($resql); print "
'; $searchpicto = $form->showFilterButtons(); print $searchpicto; print ''; print $form->selectDate(dol_print_date($search_date_sync, "%Y-%m-%d"), 'search_date_sync', 0, 0, 1); print $form->selectDate(dol_print_date($search_date_sync_end, "%Y-%m-%d"), 'search_date_sync_end', 0, 0, 1); print ''; print $form->selectMultiCurrency($multicurrency_code, 'search_code', 1, " code != '".$conf->currency."'", true); print ''; print ''; print ''; $searchpicto = $form->showFilterButtons(); print $searchpicto; print '
'; print '' . $form->selectMultiCurrency($obj->code, 'multicurrency_code', 1, " code != '".$conf->currency."'", true) . ''; print ''; print ''; print ''; print ''; print ''; print ''; if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined $selected = 0; if (in_array($obj->rowid, $arrayofselected)) { $selected = 1; } print 'rowid.'">'.img_picto('edit', 'edit').''; print 'rowid.'">'.img_picto('delete', 'delete').''; print ''; } print ''; print $obj->date_sync; print "'; print $obj->code; print ' - '.$obj->name.''; print "'; print $obj->rate; print "'; print $obj->rate_indirect; print "'; if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined $selected = 0; if (in_array($obj->rowid, $arrayofselected)) { $selected = 1; } print 'rowid.'">'.img_picto('edit', 'edit').''; print 'rowid.'">'.img_picto('delete', 'delete').''; print ''; } print '
"; print "
"; print '
'; } else { dol_print_error($db); } llxFooter(); $db->close();