1<?php 2/* Copyright (C) 2007-2020 Laurent Destailleur <eldy@users.sourceforge.net> 3 * Copyright (C) 2009-2018 Regis Houssin <regis.houssin@inodbox.com> 4 * Copyright (C) 2010 Juanjo Menent <jmenent@2byte.es> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <https://www.gnu.org/licenses/>. 18 */ 19 20/** 21 * \file htdocs/admin/limits.php 22 * \brief Page to setup limits 23 */ 24 25require '../main.inc.php'; 26require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; 27require_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'; 28 29// Load translation files required by the page 30$langs->loadLangs(array('companies', 'products', 'admin')); 31 32if (!$user->admin) accessforbidden(); 33 34$action = GETPOST('action', 'aZ09'); 35$currencycode = GETPOST('currencycode', 'alpha'); 36 37if (!empty($conf->multicurrency->enabled) && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) { 38 // When MULTICURRENCY_USE_LIMIT_BY_CURRENCY is on, we use always a defined currency code instead of '' even for default. 39 $currencycode = (!empty($currencycode) ? $currencycode : $conf->currency); 40} 41 42$mainmaxdecimalsunit = 'MAIN_MAX_DECIMALS_UNIT'.(!empty($currencycode) ? '_'.$currencycode : ''); 43$mainmaxdecimalstot = 'MAIN_MAX_DECIMALS_TOT'.(!empty($currencycode) ? '_'.$currencycode : ''); 44$mainmaxdecimalsshown = 'MAIN_MAX_DECIMALS_SHOWN'.(!empty($currencycode) ? '_'.$currencycode : ''); 45$mainroundingruletot = 'MAIN_ROUNDING_RULE_TOT'.(!empty($currencycode) ? '_'.$currencycode : ''); 46 47$valmainmaxdecimalsunit = GETPOST($mainmaxdecimalsunit, 'int'); 48$valmainmaxdecimalstot = GETPOST($mainmaxdecimalstot, 'int'); 49$valmainmaxdecimalsshown = GETPOST($mainmaxdecimalsshown, 'int'); 50$valmainroundingruletot = price2num(GETPOST($mainroundingruletot, 'alpha')); 51 52if ($action == 'update') 53{ 54 $error = 0; 55 $MAXDEC = 8; 56 if ($_POST[$mainmaxdecimalsunit] > $MAXDEC 57 || $_POST[$mainmaxdecimalstot] > $MAXDEC 58 || $_POST[$mainmaxdecimalsshown] > $MAXDEC) 59 { 60 $error++; 61 setEventMessages($langs->trans("ErrorDecimalLargerThanAreForbidden", $MAXDEC), null, 'errors'); 62 } 63 64 if ($_POST[$mainmaxdecimalsunit].(!empty($currencycode) ? '_'.$currencycode : '') < 0 65 || $_POST[$mainmaxdecimalstot] < 0 66 || $_POST[$mainmaxdecimalsshown] < 0) 67 { 68 $langs->load("errors"); 69 $error++; 70 setEventMessages($langs->trans("ErrorNegativeValueNotAllowed"), null, 'errors'); 71 } 72 73 if ($valmainroundingruletot) 74 { 75 if ($valmainroundingruletot * pow(10, $valmainmaxdecimalstot) < 1) 76 { 77 $langs->load("errors"); 78 $error++; 79 setEventMessages($langs->trans("ErrorMAIN_ROUNDING_RULE_TOTCanMAIN_MAX_DECIMALS_TOT"), null, 'errors'); 80 } 81 } 82 83 if (!$error) 84 { 85 dolibarr_set_const($db, $mainmaxdecimalsunit, $valmainmaxdecimalsunit, 'chaine', 0, '', $conf->entity); 86 dolibarr_set_const($db, $mainmaxdecimalstot, $valmainmaxdecimalstot, 'chaine', 0, '', $conf->entity); 87 dolibarr_set_const($db, $mainmaxdecimalsshown, $valmainmaxdecimalsshown, 'chaine', 0, '', $conf->entity); 88 89 dolibarr_set_const($db, $mainroundingruletot, $valmainroundingruletot, 'chaine', 0, '', $conf->entity); 90 91 header("Location: ".$_SERVER["PHP_SELF"]."?mainmenu=home&leftmenu=setup".(!empty($currencycode) ? '¤cycode='.$currencycode : '')); 92 exit; 93 } 94} 95 96 97/* 98 * View 99 */ 100 101$form = new Form($db); 102 103$title = $langs->trans("LimitsSetup"); 104$help_url = ''; 105 106llxHeader('', $title, $help_url); 107 108print load_fiche_titre($title, '', 'title_setup'); 109 110$aCurrencies = array($conf->currency); // Default currency always first position 111 112if (!empty($conf->multicurrency->enabled) && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) 113{ 114 require_once DOL_DOCUMENT_ROOT.'/core/lib/multicurrency.lib.php'; 115 116 $sql = 'SELECT rowid, code FROM '.MAIN_DB_PREFIX.'multicurrency'; 117 $sql .= ' WHERE entity = '.$conf->entity; 118 $sql .= ' AND code != "'.$conf->currency.'"'; // Default currency always first position 119 $resql = $db->query($sql); 120 if ($resql) 121 { 122 while ($obj = $db->fetch_object($resql)) 123 { 124 $aCurrencies[] = $obj->code; 125 } 126 } 127 128 if (!empty($aCurrencies) && count($aCurrencies) > 1) 129 { 130 $head = multicurrencyLimitPrepareHead($aCurrencies); 131 132 print dol_get_fiche_head($head, $currencycode, '', -1, ''); 133 } 134} 135 136print '<span class="opacitymedium">'.$langs->trans("LimitsDesc")."</span><br>\n"; 137print "<br>\n"; 138 139if ($action == 'edit') 140{ 141 print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">'; 142 print '<input type="hidden" name="token" value="'.newToken().'">'; 143 print '<input type="hidden" name="action" value="update">'; 144 if (!empty($conf->multicurrency->enabled) && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) { 145 print '<input type="hidden" name="currencycode" value="'.$currencycode.'">'; 146 } 147 148 clearstatcache(); 149 150 print '<table class="noborder centpercent">'; 151 print '<tr class="liste_titre"><td>'.$langs->trans("Parameters").'</td><td>'.$langs->trans("Value").'</td></tr>'; 152 153 print '<tr class="oddeven"><td>'; 154 print $form->textwithpicto($langs->trans("MAIN_MAX_DECIMALS_UNIT"), $langs->trans("ParameterActiveForNextInputOnly")); 155 print '</td><td><input class="flat" name="'.$mainmaxdecimalsunit.'" size="3" value="'.(isset($conf->global->$mainmaxdecimalsunit) ? $conf->global->$mainmaxdecimalsunit : $conf->global->MAIN_MAX_DECIMALS_UNIT).'"></td></tr>'; 156 157 print '<tr class="oddeven"><td>'; 158 print $form->textwithpicto($langs->trans("MAIN_MAX_DECIMALS_TOT"), $langs->trans("ParameterActiveForNextInputOnly")); 159 print '</td><td><input class="flat" name="'.$mainmaxdecimalstot.'" size="3" value="'.(isset($conf->global->$mainmaxdecimalstot) ? $conf->global->$mainmaxdecimalstot : $conf->global->MAIN_MAX_DECIMALS_TOT).'"></td></tr>'; 160 161 print '<tr class="oddeven"><td>'.$langs->trans("MAIN_MAX_DECIMALS_SHOWN").'</td>'; 162 print '<td><input class="flat" name="'.$mainmaxdecimalsshown.'" size="3" value="'.(isset($conf->global->$mainmaxdecimalsshown) ? $conf->global->$mainmaxdecimalsshown : $conf->global->MAIN_MAX_DECIMALS_SHOWN).'"></td></tr>'; 163 164 print '<tr class="oddeven"><td>'; 165 print $form->textwithpicto($langs->trans("MAIN_ROUNDING_RULE_TOT"), $langs->trans("ParameterActiveForNextInputOnly")); 166 print '</td><td><input class="flat" name="'.$mainroundingruletot.'" size="3" value="'.(isset($conf->global->$mainroundingruletot) ? $conf->global->$mainroundingruletot : $conf->global->MAIN_ROUNDING_RULE_TOT).'"></td></tr>'; 167 168 print '</table>'; 169 170 print '<br>'; 171 print '<div class="center">'; 172 print '<input class="button button-save" type="submit" value="'.$langs->trans("Save").'">'; 173 print '</div>'; 174 print '<br>'; 175 176 print '</form>'; 177 print '<br>'; 178} else { 179 print '<div class="div-table-responsive-no-min">'; 180 print '<table class="noborder centpercent">'; 181 print '<tr class="liste_titre"><td>'.$langs->trans("Parameter").'</td><td>'.$langs->trans("Value").'</td></tr>'; 182 183 print '<tr class="oddeven"><td>'; 184 print $form->textwithpicto($langs->trans("MAIN_MAX_DECIMALS_UNIT"), $langs->trans("ParameterActiveForNextInputOnly")); 185 print '</td><td align="right">'.(isset($conf->global->$mainmaxdecimalsunit) ? $conf->global->$mainmaxdecimalsunit : $conf->global->MAIN_MAX_DECIMALS_UNIT).'</td></tr>'; 186 187 print '<tr class="oddeven"><td>'; 188 print $form->textwithpicto($langs->trans("MAIN_MAX_DECIMALS_TOT"), $langs->trans("ParameterActiveForNextInputOnly")); 189 print '</td><td align="right">'.(isset($conf->global->$mainmaxdecimalstot) ? $conf->global->$mainmaxdecimalstot : $conf->global->MAIN_MAX_DECIMALS_TOT).'</td></tr>'; 190 191 print '<tr class="oddeven"><td>'.$langs->trans("MAIN_MAX_DECIMALS_SHOWN").'</td>'; 192 print '<td align="right">'.(isset($conf->global->$mainmaxdecimalsshown) ? $conf->global->$mainmaxdecimalsshown : $conf->global->MAIN_MAX_DECIMALS_SHOWN).'</td></tr>'; 193 194 print '<tr class="oddeven"><td>'; 195 print $form->textwithpicto($langs->trans("MAIN_ROUNDING_RULE_TOT"), $langs->trans("ParameterActiveForNextInputOnly")); 196 print '</td><td align="right">'.(isset($conf->global->$mainroundingruletot) ? $conf->global->$mainroundingruletot : $conf->global->MAIN_ROUNDING_RULE_TOT).'</td></tr>'; 197 198 print '</table>'; 199 print '</div>'; 200 201 print '<div class="tabsAction">'; 202 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=edit'.(!empty($currencycode) ? '¤cycode='.$currencycode : '').'">'.$langs->trans("Modify").'</a>'; 203 print '</div>'; 204} 205 206if (!empty($conf->multicurrency->enabled) && !empty($conf->global->MULTICURRENCY_USE_LIMIT_BY_CURRENCY)) 207{ 208 if (!empty($aCurrencies) && count($aCurrencies) > 1) 209 { 210 print dol_get_fiche_end(); 211 } 212} 213 214if (empty($mysoc->country_code)) 215{ 216 $langs->load("errors"); 217 $warnpicto = img_warning($langs->trans("WarningMandatorySetupNotComplete")); 218 print '<br><a href="'.DOL_URL_ROOT.'/admin/company.php?mainmenu=home">'.$warnpicto.' '.$langs->trans("WarningMandatorySetupNotComplete").'</a>'; 219} else { 220 // Show examples 221 print load_fiche_titre($langs->trans("ExamplesWithCurrentSetup"), '', ''); 222 223 print '<span class="opacitymedium">'.$langs->trans("Format").':</span> '.price(price2num(1234.56789, 'MT'), 0, $langs, 1, -1, -1, $currencycode)."<br>\n"; 224 225 // Always show vat rates with vat 0 226 $s = 2 / 7; $qty = 1; $vat = 0; 227 $tmparray = calcul_price_total(1, $qty * price2num($s, 'MU'), 0, $vat, 0, 0, 0, 'HT', 0, 0, $mysoc); 228 print '<span class="opacitymedium">'.$langs->trans("UnitPriceOfProduct").":</span> ".price2num($s, 'MU'); 229 print " x ".$langs->trans("Quantity").": ".$qty; 230 print " - ".$langs->trans("VAT").": ".$vat.'%'; 231 print ' -> <span class="opacitymedium">'.$langs->trans("TotalPriceAfterRounding").":</span> ".$tmparray[0].' / '.$tmparray[1].' / '.$tmparray[2]."<br>\n"; 232 233 $s = 10 / 3; $qty = 1; $vat = 0; 234 $tmparray = calcul_price_total(1, $qty * price2num($s, 'MU'), 0, $vat, 0, 0, 0, 'HT', 0, 0, $mysoc); 235 print '<span class="opacitymedium">'.$langs->trans("UnitPriceOfProduct").":</span> ".price2num($s, 'MU'); 236 print " x ".$langs->trans("Quantity").": ".$qty; 237 print " - ".$langs->trans("VAT").": ".$vat.'%'; 238 print ' -> <span class="opacitymedium">'.$langs->trans("TotalPriceAfterRounding").":</span> ".$tmparray[0].' / '.$tmparray[1].' / '.$tmparray[2]."<br>\n"; 239 240 $s = 10 / 3; $qty = 2; $vat = 0; 241 $tmparray = calcul_price_total(1, $qty * price2num($s, 'MU'), 0, $vat, 0, 0, 0, 'HT', 0, 0, $mysoc); 242 print '<span class="opacitymedium">'.$langs->trans("UnitPriceOfProduct").":</span> ".price2num($s, 'MU'); 243 print " x ".$langs->trans("Quantity").": ".$qty; 244 print " - ".$langs->trans("VAT").": ".$vat.'%'; 245 print ' -> <span class="opacitymedium">'.$langs->trans("TotalPriceAfterRounding").":</span> ".$tmparray[0].' / '.$tmparray[1].' / '.$tmparray[2]."<br>\n"; 246 247 // Add vat rates examples specific to country 248 $vat_rates = array(); 249 250 $sql = "SELECT taux as vat_rate, t.code as vat_code, t.localtax1 as localtax_rate1, t.localtax2 as localtax_rate2"; 251 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; 252 $sql .= " WHERE t.active=1 AND t.fk_pays = c.rowid AND c.code='".$db->escape($mysoc->country_code)."' AND (t.taux <> 0 OR t.localtax1 <>0 OR t.localtax2 <>0)"; 253 $sql .= " ORDER BY t.taux ASC"; 254 $resql = $db->query($sql); 255 if ($resql) 256 { 257 $num = $db->num_rows($resql); 258 if ($num) 259 { 260 for ($i = 0; $i < $num; $i++) 261 { 262 $obj = $db->fetch_object($resql); 263 $vat_rates[] = array('vat_rate'=>$obj->vat_rate, 'code'=>$obj->vat_code, 'localtax_rate1'=>$obj->localtax_rate1, 'locltax_rate2'=>$obj->localtax_rate2); 264 } 265 } 266 } else dol_print_error($db); 267 268 if (count($vat_rates)) 269 { 270 foreach ($vat_rates as $vatarray) 271 { 272 $vat = $vatarray['vat_rate']; 273 for ($qty = 1; $qty <= 2; $qty++) 274 { 275 $vattxt = $vat.($vatarray['code'] ? ' ('.$vatarray['code'].')' : ''); 276 277 $localtax_array = getLocalTaxesFromRate($vattxt, 0, $mysoc, $mysoc); 278 279 $s = 10 / 3; 280 $tmparray = calcul_price_total($qty, price2num($s, 'MU'), 0, $vat, -1, -1, 0, 'HT', 0, 0, $mysoc, $localtax_array); 281 print '<span class="opacitymedium">'.$langs->trans("UnitPriceOfProduct").":</span> ".price2num($s, 'MU'); 282 print " x ".$langs->trans("Quantity").": ".$qty; 283 print " - ".$langs->trans("VAT").": ".$vat.'%'; 284 print ($vatarray['code'] ? ' ('.$vatarray['code'].')' : ''); 285 print ' -> <span class="opacitymedium">'.$langs->trans("TotalPriceAfterRounding").":</span> "; 286 print $tmparray[0].' / '.$tmparray[1].($tmparray[9] ? '+'.$tmparray[9] : '').($tmparray[10] ? '+'.$tmparray[10] : '').' / '.$tmparray[2]; 287 print "<br>\n"; 288 } 289 } 290 } else { 291 // More examples if not specific vat rate found 292 // This example must be kept for test purpose with current value because value used (2/7, 10/3, and vat 0, 10) 293 // were calculated to show all possible cases of rounding. If we change this, examples becomes useless or show the same rounding rule. 294 295 $localtax_array = array(); 296 297 $s = 10 / 3; $qty = 1; $vat = 10; 298 $tmparray = calcul_price_total($qty, price2num($s, 'MU'), 0, $vat, -1, -1, 0, 'HT', 0, 0, $mysoc, $localtax_array); 299 print '<span class="opacitymedium">'.$langs->trans("UnitPriceOfProduct").":</span> ".price2num($s, 'MU'); 300 print " x ".$langs->trans("Quantity").": ".$qty; 301 print " - ".$langs->trans("VAT").": ".$vat.'%'; 302 print ' -> <span class="opacitymedium">'.$langs->trans("TotalPriceAfterRounding").":</span> ".$tmparray[0].' / '.$tmparray[1].' / '.$tmparray[2]."<br>\n"; 303 304 $s = 10 / 3; $qty = 2; $vat = 10; 305 $tmparray = calcul_price_total($qty, price2num($s, 'MU'), 0, $vat, -1, -1, 0, 'HT', 0, 0, $mysoc, $localtax_array); 306 print '<span class="opacitymedium">'.$langs->trans("UnitPriceOfProduct").":</span> ".price2num($s, 'MU'); 307 print " x ".$langs->trans("Quantity").": ".$qty; 308 print " - ".$langs->trans("VAT").": ".$vat.'%'; 309 print ' -> <span class="opacitymedium">'.$langs->trans("TotalPriceAfterRounding").":</span> ".$tmparray[0].' / '.$tmparray[1].' / '.$tmparray[2]."<br>\n"; 310 } 311} 312 313// End of page 314llxFooter(); 315$db->close(); 316