diff --git a/htdocs/admin/limits.php b/htdocs/admin/limits.php index a7cefb6faab506628f1fd415f2cbe23c76ff9fbc..231f40e306c94d27554a272fa6f36577906da04e 100644 --- a/htdocs/admin/limits.php +++ b/htdocs/admin/limits.php @@ -25,6 +25,7 @@ require("./pre.inc.php"); require_once(DOL_DOCUMENT_ROOT."/lib/admin.lib.php"); +require_once(DOL_DOCUMENT_ROOT."/lib/price.lib.php"); $langs->load("companies"); $langs->load("products"); @@ -36,19 +37,42 @@ if (!$user->admin) if (isset($_POST["action"]) && $_POST["action"] == 'update') { + $error=0; $MAXDEC=8; if ($_POST["MAIN_MAX_DECIMALS_UNIT"] > $MAXDEC || $_POST["MAIN_MAX_DECIMALS_TOT"] > $MAXDEC || $_POST["MAIN_MAX_DECIMALS_SHOWN"] > $MAXDEC) { + $error++; $mesg='<div class="error">'.$langs->trans("ErrorDecimalLargerThanAreForbidden",$MAXDEC).'</div>'; } - else + + if ($_POST["MAIN_MAX_DECIMALS_UNIT"] < 0 + || $_POST["MAIN_MAX_DECIMALS_TOT"] < 0 + || $_POST["MAIN_MAX_DECIMALS_SHOWN"] < 0) + { + $langs->load("errors"); + $error++; + $mesg='<div class="error">'.$langs->trans("ErrorNegativeValueNotAllowed").'</div>'; + } + + if ($_POST["MAIN_ROUNDING_RULE_TOT"]) + { + if ($_POST["MAIN_ROUNDING_RULE_TOT"] * pow(10,$_POST["MAIN_MAX_DECIMALS_TOT"]) < 1) + { + $langs->load("errors"); + $error++; + $mesg='<div class="error">'.$langs->trans("ErrorMAIN_ROUNDING_RULE_TOTCanMAIN_MAX_DECIMALS_TOT").'</div>'; + } + } + + if (! $error) { dolibarr_set_const($db, "MAIN_MAX_DECIMALS_UNIT", $_POST["MAIN_MAX_DECIMALS_UNIT"],'chaine',0,'',$conf->entity); dolibarr_set_const($db, "MAIN_MAX_DECIMALS_TOT", $_POST["MAIN_MAX_DECIMALS_TOT"],'chaine',0,'',$conf->entity); dolibarr_set_const($db, "MAIN_MAX_DECIMALS_SHOWN", $_POST["MAIN_MAX_DECIMALS_SHOWN"],'chaine',0,'',$conf->entity); - dolibarr_set_const($db, "MAIN_DISABLE_PDF_COMPRESSION", $_POST["MAIN_DISABLE_PDF_COMPRESSION"],'chaine',0,'',$conf->entity); + + dolibarr_set_const($db, "MAIN_ROUNDING_RULE_TOT", $_POST["MAIN_ROUNDING_RULE_TOT"],'chaine',0,'',$conf->entity); Header("Location: ".$_SERVER["PHP_SELF"]."?mainmenu=home&leftmenu=setup"); exit; @@ -56,6 +80,11 @@ if (isset($_POST["action"]) && $_POST["action"] == 'update') } + +/* + * View + */ + $html=new Form($db); llxHeader(); @@ -93,12 +122,10 @@ if (isset($_GET["action"]) && $_GET["action"] == 'edit') $var=!$var; print '<tr '.$bc[$var].'><td>'.$langs->trans("MAIN_MAX_DECIMALS_SHOWN").'</td><td><input class="flat" name="MAIN_MAX_DECIMALS_SHOWN" size="3" value="' . $conf->global->MAIN_MAX_DECIMALS_SHOWN . '"></td></tr>'; - /* $var=!$var; - print '<tr '.$bc[$var].'><td>'.$langs->trans("MAIN_DISABLE_PDF_COMPRESSION").'</td><td>'; - print $html->selectyesno('MAIN_DISABLE_PDF_COMPRESSION',$conf->global->MAIN_DISABLE_PDF_COMPRESSION); - print '</td></tr>'; - */ + print '<tr '.$bc[$var].'><td>'; + print $html->textwithpicto($langs->trans("MAIN_ROUNDING_RULE_TOT"),$langs->trans("ParameterActiveForNextInputOnly")); + print '</td><td><input class="flat" name="MAIN_ROUNDING_RULE_TOT" size="3" value="' . $conf->global->MAIN_ROUNDING_RULE_TOT . '"></td></tr>'; print '</table>'; @@ -129,10 +156,10 @@ else $var=!$var; print '<tr '.$bc[$var].'><td>'.$langs->trans("MAIN_MAX_DECIMALS_SHOWN").'</td><td align="right">'.$conf->global->MAIN_MAX_DECIMALS_SHOWN.'</td></tr>'; - /* $var=!$var; - print '<tr '.$bc[$var].'><td>'.$langs->trans("MAIN_DISABLE_PDF_COMPRESSION").'</td><td align="right">'.yn($conf->global->MAIN_DISABLE_PDF_COMPRESSION).'</td></tr>'; - */ + print '<tr '.$bc[$var].'><td>'; + print $html->textwithpicto($langs->trans("MAIN_ROUNDING_RULE_TOT"),$langs->trans("ParameterActiveForNextInputOnly")); + print '</td><td align="right">'.$conf->global->MAIN_ROUNDING_RULE_TOT.'</td></tr>'; print '</table>'; @@ -142,6 +169,44 @@ else } +// Show examples +print '<b>'.$langs->trans("Examples").":</b><br>\n"; + +$s=2/7;$qty=1;$vat=0; +$tmparray=calcul_price_total(1,$qty*price2num($s,'MU'),0,$vat,0,'HT',0); +print $langs->trans("UnitPriceOfProduct").": ".price2num($s,'MU'); +print " x ".$langs->trans("Quantity").": ".$qty; +print " - ".$langs->trans("VAT").": ".$vat; +print " -> ".$langs->trans("TotalPriceAfterRounding").": ".$tmparray[2]."<br>\n"; + +$s=10/3;$qty=1;$vat=0; +$tmparray=calcul_price_total(1,$qty*price2num($s,'MU'),0,$vat,0,'HT',0); +print $langs->trans("UnitPriceOfProduct").": ".price2num($s,'MU'); +print " x ".$langs->trans("Quantity").": ".$qty; +print " - ".$langs->trans("VAT").": ".$vat; +print " -> ".$langs->trans("TotalPriceAfterRounding").": ".$tmparray[2]."<br>\n"; + +$s=10/3;$qty=2;$vat=0; +$tmparray=calcul_price_total(1,$qty*price2num($s,'MU'),0,$vat,0,'HT',0); +print $langs->trans("UnitPriceOfProduct").": ".price2num($s,'MU'); +print " x ".$langs->trans("Quantity").": ".$qty; +print " - ".$langs->trans("VAT").": ".$vat; +print " -> ".$langs->trans("TotalPriceAfterRounding").": ".$tmparray[2]."<br>\n"; + +$s=10/3;$qty=1;$vat=10; +$tmparray=calcul_price_total(1,$qty*price2num($s,'MU'),0,$vat,0,'HT',0); +print $langs->trans("UnitPriceOfProduct").": ".price2num($s,'MU'); +print " x ".$langs->trans("Quantity").": ".$qty; +print " - ".$langs->trans("VAT").": ".$vat; +print " -> ".$langs->trans("TotalPriceAfterRounding").": ".$tmparray[2]."<br>\n"; + +$s=10/3;$qty=2;$vat=10; +$tmparray=calcul_price_total(1,$qty*price2num($s,'MU'),0,$vat,0,'HT',0); +print $langs->trans("UnitPriceOfProduct").": ".price2num($s,'MU'); +print " x ".$langs->trans("Quantity").": ".$qty; +print " - ".$langs->trans("VAT").": ".$vat; +print " -> ".$langs->trans("TotalPriceAfterRounding").": ".$tmparray[2]."<br>\n"; + $db->close(); llxFooter('$Date$ - $Revision$'); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index fde126f8b77086432649e92e0722f40f9aa1c238..804e31c3fbff2ecf341134bd68bb437555e1ad30 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -713,6 +713,9 @@ MAIN_MAX_DECIMALS_UNIT=Max decimals for unit prices MAIN_MAX_DECIMALS_TOT=Max decimals for total prices MAIN_MAX_DECIMALS_SHOWN=Max decimals for prices shown on screen (Add <b>...</b> after this number if you want to see <b>...</b> when number is truncated when shown on screen) MAIN_DISABLE_PDF_COMPRESSION=Use PDF compression for generated PDF files. +MAIN_ROUNDING_RULE_TOT = Size of rounding range (for rare countries where rounding is done on something else than base 10) +UnitPriceOfProduct=Net unit price of a product +TotalPriceAfterRounding=Total price inc. tax after rounding ParameterActiveForNextInputOnly=Parameter effective for next input only NoEventOrNoAuditSetup=No security event has been recorded yet. This can be normal if audit has not been enabled on "setup - security - audit" page. NoEventFoundWithCriteria=No security event has been found for such search criterias. diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index eb2b7ff452821ea0d48b07aca5a32bfac8ba5e4e..05e1450075f363052fcd42b939fdc1d82bee2fa0 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -428,6 +428,7 @@ NotAllowed=Not allowed ReadPermissionNotAllowed=Read permission not allowed AmountInCurrency=Amount in %s currency Example=Example +Examples=Examples NoExample=No example FindBug=Report a bug NbOfThirdParties=Number of third parties diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index ccb9264d152947fb42e05d32b0ab3c9bbf7120e1..33d4c55ba08d2b0d0524e3c768bb738c99226da8 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -713,6 +713,9 @@ MAIN_MAX_DECIMALS_UNIT = Nombre de décimales maximum pour les prix unitaires MAIN_MAX_DECIMALS_TOT = Nombre de décimales maximum pour les prix totaux MAIN_MAX_DECIMALS_SHOWN = Nombre de décimales maximum pour les montant affichés à l'écran (Mettre <b>...</b> après ce nombre max si vous voulez voir <b>...</b> quand le nombre est tronqué à l'affichage écran) MAIN_DISABLE_PDF_COMPRESSION = Utiliser la compression PDF pour les fichiers PDF générés. +MAIN_ROUNDING_RULE_TOT = Taille du pas des arrondis (pour les très rares pays qui arrondissent sur une autre base que la base 10) +UnitPriceOfProduct=Prix unitaire HT d'un produit +TotalPriceAfterRounding=Prix total TTC après arrondis ParameterActiveForNextInputOnly = Parametre effectif pour les prochaines saisies uniquement NoEventOrNoAuditSetup = Aucun évenement d'audit de sécurité n'a été enregistré. Ceci peut etre normal si l'audit n'a pas été activé dans la configuration - sécurité - audit. NoEventFoundWithCriteria = Aucun évenement d'audit de sécurité trouvé avec ces critères. diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index e55bf746ff3ecf6a1f25e8bc6626907817ad61bf..449842410ef813fbfdf673e0579335624da66997 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -427,6 +427,7 @@ NotAllowed=Non autorisé ReadPermissionNotAllowed=Lecture non autorisée AmountInCurrency=Montants exprimés en %s Example=Exemple +Examples=Exemples NoExample=Pas d'exemple FindBug=Signaler un bug NbOfThirdParties=Nombre de tiers diff --git a/htdocs/lib/price.lib.php b/htdocs/lib/price.lib.php index 1733674eaa787c1be69ec59f2085a0b1990d8695..9e34dccf19f0aa5c68d740fa312782c5fa53d81a 100644 --- a/htdocs/lib/price.lib.php +++ b/htdocs/lib/price.lib.php @@ -27,8 +27,7 @@ /** * \brief Permet de calculer les parts total HT, TVA et TTC d'une ligne de * facture, propale, commande ou autre depuis: - * quantity, unit price, remise_percent_ligne, txtva, remise_percent_global, price_base_type, info_bits - * \param qty Quantity + * quantity, unit price, remise_percent_ligne, txtva, remise_percent_global, price_base_type, info_bits * \param qty Quantity * \param pu Prix unitaire (HT ou TTC selon price_base_type) * \param remise_percent_ligne Remise ligne * \param txtva Taux tva @@ -59,7 +58,13 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $remise_pe $result[0] = price2num($tot_avec_remise, 'MT'); $result[2] = price2num($tot_avec_remise * ( 1 + ( (($info_bits & 1)?0:$txtva) / 100)), 'MT'); // Selon TVA NPR ou non $result2bis= price2num($tot_avec_remise * ( 1 + ( $txtva / 100)), 'MT'); // Si TVA consideree normale (non NPR) - $result[1] = $result2bis - $result[0]; + if (! empty($conf->global->MAIN_ROUNDING_RULE_TOT)) + { + $result[0]=round($result[0]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT; + $result[2]=round($result[2]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT; + $result2bis=round($result2bis/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT; + } + $result[1] = $result2bis - $result[0]; // Total VAT = TTC - HT $result[3] = price2num($pu, 'MU'); $result[5] = price2num($pu * ( 1 + ((($info_bits & 1)?0:$txtva) / 100)), 'MU'); // Selon TVA NPR ou non @@ -68,8 +73,7 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $remise_pe } else { - // On cacule a l'envers en partant du prix TTC - // Utilise pour les produits a prix TTC reglemente (livres, ...) + // On calcule à l'envers en partant du prix TTC $tot_sans_remise = $pu * $qty; $tot_avec_remise_ligne = $tot_sans_remise * ( 1 - ($remise_percent_ligne / 100)); $tot_avec_remise = $tot_avec_remise_ligne * ( 1 - ($remise_percent_global / 100)); @@ -82,7 +86,13 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $remise_pe $result[2] = price2num($tot_avec_remise, 'MT'); $result[0] = price2num($tot_avec_remise / ( 1 + ((($info_bits & 1)?0:$txtva) / 100)), 'MT'); // Selon TVA NPR ou non $result0bis= price2num($tot_avec_remise / ( 1 + ($txtva / 100)), 'MT'); // Si TVA consideree normale (non NPR) - $result[1] = $result[2] - $result0bis; + if (! empty($conf->global->MAIN_ROUNDING_RULE_TOT)) + { + $result0bis=round($result0bis/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT; + $result[0]=round($result[0]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT; + $result[2]=round($result[2]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT; + } + $result[1] = $result[2] - $result0bis; // Total VAT = TTC - HT $result[5] = price2num($pu, 'MU'); $result[3] = price2num($pu / ( 1 + ((($info_bits & 1)?0:$txtva) / 100)), 'MU'); // Selon TVA NPR ou non