Correct pennies in Boletophp Bank Slips

Asked

Viewed 671 times

6

I’m using the Boletophp project to generate bank slips, but I noticed that the pennies are not recorded correctly, because when I buy a product with the value of for example, R $ 245,00 plus the bank rate R $ 2,95, it prints correctly the amount of R $ 247,95.

But when I buy a product with the value of 2.399,99 plus the bank rate of R $ 2,95, it prints the value of R $ 2.401,95, when the correct would be R $ 2.402,94.

In other words, he ignores the pennies of the products, but he doesn’t ignore the pennies of the bank tax.

Friends could tell me where I’m going wrong, or what the solution would be for him to print the pennies of the products as well.

In the Database I am writing in the column as type "decimal(10,2)".

Below I relate the code line of the boleto related to the value.

   $dias_de_prazo_para_pagamento = 5;
   $taxa_boleto = 2.95;
   $data_venc = date("d/m/Y", time() + (5 * 86400));  // Prazo de X dias OU informe data: "13/04/2006"; 
   $valor_cobrado = $_POST["total"]; // Valor - REGRA: Sem pontos na milhar e tanto faz com "." ou "," ou com 1 ou 2 ou sem casa decimal
   $valor_cobrado = str_replace(".", "",$valor_cobrado);
   $valor_boleto=number_format($valor_cobrado+$taxa_boleto,2,",",".");

Below I list the code line of the form referring to the value.

   <?php
   if(count($_SESSION['carrinho']) == 0){
      echo '<tr><td colspan="5">Não há produto no carrinho</td></tr>';
   }else{
      require("conexao.php");
   $total = 0;
      foreach($_SESSION['carrinho'] as $codigo => $qtd){
   $sql   = "SELECT * FROM produto WHERE codigo= '$codigo'";
   $qr    = mysql_query($sql) or die(mysql_error());
   $ln    = mysql_fetch_assoc($qr);

   $titulo  = $ln['titulo'];
   $preco = number_format($ln['preco'], 2, ',', '.');
   $sub   = number_format($ln['preco'] * $qtd, 2, ',', '.');

   $total += $ln['preco'] * $qtd;

      echo '<tr style="font-size:11px; font-weight:bold; color:#000;">       
                <td  align="left">'.$titulo.'</td>
                <td align="center">'.$qtd.'</td>
                <td align="center">R$ '.$preco.'</td>
                <td align="center">R$ '.$sub.'</td>
                <td align="center"><a href="?acao=del&codigo='.$codigo.'">
                <img width="25" src="img/del.png" title="Remover '.$titulo.'"/>
                </a></td>
             </tr>';
    }
    $total = number_format($total, 2, ',', '.');
       echo '<tr></tr><tr></tr><tr></tr><tr></tr><tr></tr>
             <tr>
                <td align="right" style="font-size:16px; font-weight:bold; color:#990000;" colspan="3">Total</td>
                <td align="left" style="font-size:16px; font-weight:bold; color:#000;" colspan="4">R$ '.$total.'</td>
              </tr>';
    }
    ?>

How do I get the billet to print the pennies of the products?

  • 1

    Can format the currency value thus

3 answers

3


The problem is that PHP, like all languages, does not work well with accurate monetary values.

I find it curious that a program ready to work with monetary values does not handle this well.

Has several questions here about this, but so far no one wanted to make one specific for PHP.

The processor works very well with decimal values but to have performance it does it based on 2. So you can not accurately represent all values.

Most programmers do not know this and cause problems for their software users. The difference may be a dime, but if you multiply a dime by a million, that’s 10,000 reais of loss to one side or the other. It can generate legal proceedings or fine in supervision.

Then you need to treat monetary values differently. Mysql has a proper shape, several languages have a data type that handles the number otherwise to avoid this accuracy problem. All treatment should be done on the basis of 10. In general this is done with an integer and scale to represent the decimal part. Integers do not suffer from this problem. This can be done transparently in many languages. This is not the case for PHP.

The solution is to do manual, or create a new type of data that encapsulates this logic, or use something ready.

Manually treat the amounts by the cents for all accounts and only in the presentation use the comma. If you treat the numbers by the cents, a whole solves the problem. Instead of having 245,00 reais, you will have 24500 cents.

Of course you have to know how to do some operations, like multiplication and division to not give scale problem. Divisions and multiplications by 100 will be common (assuming there are two decimal places).

To avoid doing this all the time and forgetting something, some people encapsulate it in a class Decimal or Money abstracting operations a little and making the use more natural.

There are some of these classes ready. PHP itself has an additional module called Bcmath. I don’t like it much, but it’s a ready-made solution.

In any case the presentation of the data is different from the data itself. It is no use solving the problem of presentation if the calculations, which is important, remain wrong.

3

The PHP account is right 2399 plus 2.95 is 2.401.95. This happens because transforming the string 2.399,99 In float the 99 cents is discarded because the separate of is . and not virgular.

A string in which the first character is a number, PHP will treat this as a number so the expression "2 + '6 apples'" equals 8?

$a = 10;
$b = (float)'20,1';

echo $a + $b;

The expected result would be 30.1 right? no! , just 20 is considered a numerical value, for the expected result the value should be 20.1. If the value of $b were 20#%$99 and added to $a the exit would still be 30.

Error simulation:

$taxa_boleto = 2.95;
$valor_cobrado = '2.399,99';
$valor_cobrado =  str_replace(".", "", $valor_cobrado);
$res = $valor_cobrado + $taxa_boleto;
$valor_boleto = number_format($valor_cobrado + $taxa_boleto, 2, ",", ".");

The output is 2401.95. The account made was 2399 + 2.95

Solution of the separator changed from , for .

$taxa_boleto = 2.95;
$valor_cobrado = '2.399,99';
$valor_cobrado =  str_replace(".", "", $valor_cobrado);
$valor_cobrado =  str_replace(",", ".", $valor_cobrado); //linha adicionada
$res = $valor_cobrado + $taxa_boleto;
echo $res;

Output: 2402.94. Account made was 2399.99 + 2.95

1

Hello, I would like to thank the rray because with your tip I managed to make the boleto print correctly "(including the cents of the products)" the values of the products added or not the banking fees.

I changed the following lines below the code.

Ignoring pennies from products - Wrong

 $valor_cobrado = str_replace(".", "",$valor_cobrado);
 $valor_boleto=number_format($valor_cobrado+$taxa_boleto,2,",",".");

Including Product Pennies - Correct

 $valor_cobrado = str_replace(",", "",$valor_cobrado);
 $valor_boleto=number_format($valor_cobrado+$taxa_boleto,2,".",".");

I tested it on bank slips: Banco do Brasil, Caixa Econômica, Itaú, Bradesco, Santander, and worked in all.

I hope you help other Boletophp users.

Thank you, and hugs to everyone.

  • When working with monetary values, set the database column type to DECIMAL(20, 6), for example. This will allow higher decimal accuracy. A common problem is that many inexperienced programmers confuse the visual format of a monetary value with the mathematical standard. In mathematics, there is no comma to identify decimal or millennial. The unique identifier is the point (.), which indicates fractional value.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.