Jump to content

cart round method


ruisonika

Recommended Posts

Hello i am stuck with a problem on round method in prestashop 1.6.
In shopping cart after choose shipping method, in last step (5) of checkout i have:

  1. the sum of products without tax - ok
  2. the shipping without tax - ok 
  3. the subtotal (products + shipp) without tax - ok
  4. the total tax - wrong
  5. the total cart - wrong

Example:
product price 32,90 euros x 1
total products - 32,90 euros
total shipp - 4,50 euros
sub total - 37,40 euros
total tax - 8,61 euros (it should be 8,60)
total of order - 46,01 (and it should be 46,00 euros)
 

How can i fix it?
 

Captura de ecrã 2020-11-09, às 15.31.45.png

Link to comment
Share on other sites

This view is correct.
Change the display administration to 3 decimal places.
Then you will see the difference.
If you have rounding to two tenths and the sum is eg 8.616235 then the rounding result is correct.

Link to comment
Share on other sites

Wrong proposal - correct bellow

imho all values are rounded to 2 decimals. (the first three values come from product price or shipping price and therefore are seemingly rounded to 1 decimal.

Change the configuration value "PS_PRICE_DISPLAY_PRECISION" from the value 2 to value 1

Edited by EvaF (see edit history)
Link to comment
Share on other sites

Yes, you are right :( I didn't read displayPrice to the end and expected that they distinguish in format

$currency->decimals 

and

 $c_decimals = (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_;

so only one option that comes on my mind is override Tools::displayPrice

 

 

Link to comment
Share on other sites

Just now, EvaF said:

Yes, you are right :( I didn't read displayPrice to the end and expected that they distinguish in format


$currency->decimals 

and


 $c_decimals = (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_;

so only one option that comes on my mind is override Tools::displayPrice

 

 

In Prestashop 1.6 the display is a bit more complicated than in 1.7.

Link to comment
Share on other sites

😁 I solved it in the Czech forum: 😎

https://www.prestashop.com/forums/topic/1034842-zaokrouhlovani-cen/

 

switch ($c_format)
		    {
			    case 1:
				    $ret = $c_char.$blank.number_format($price, $c_decimals, '.', ',');
				    break;
			    case 2:
				    $ret = number_format($price, $c_decimals, ',', ' ').$blank.$c_char;
				    break;
			    case 3:
				    $ret = $c_char.$blank.number_format($price, $c_decimals, ',', '.');
				    break;
			    case 4:
				    $ret = number_format($price, $c_decimals, '.', ',').$blank.$c_char;
				    break;
			    case 5:
				    $ret = $c_char.$blank.number_format($price, $c_decimals, '.', "'");
				    break;
		    }

 

Edited by Guest (see edit history)
Link to comment
Share on other sites

    public static function displayPrice($price, $currency = null, $no_utf8 = false, Context $context = null)
    {
        if (!is_numeric($price)) {
            return $price;
        }
        if (!$context) {
            $context = Context::getContext();
        }
        if ($currency === null) {
            $currency = $context->currency;
        } elseif (is_int($currency)) {
            $currency = Currency::getCurrencyInstance((int)$currency);
        }

        if (is_array($currency)) {
            $c_char = $currency['sign'];
            $c_format = $currency['format'];
// change
            $c_decimals = (int)$currency['decimals'];
			
            $c_blank = $currency['blank'];
        } elseif (is_object($currency)) {
            $c_char = $currency->sign;
            $c_format = $currency->format;
// change
            $c_decimals = (int)$currency->decimals ;
            $c_blank = $currency->blank;
        } else {
            return false;
        }
// change
        $c_decimalsrounded = (int)$c_decimals ;
// =currency decimals (=1)
        $c_decimals = (int)$c_decimals * _PS_PRICE_DISPLAY_PRECISION_;
// display precison (=  1 * 2)

        $blank = ($c_blank ? ' ' : '');
        $ret = 0;
        if (($is_negative = ($price < 0))) {
            $price *= -1;
        }
// changed                                          
        $price = Tools::ps_round($price, $c_decimalsrounded);

        /*
        * If the language is RTL and the selected currency format contains spaces as thousands separator
        * then the number will be printed in reverse since the space is interpreted as separating words.
        * To avoid this we replace the currency format containing a space with the one containing a comma (,) as thousand
        * separator when the language is RTL.
        *
        * TODO: This is not ideal, a currency format should probably be tied to a language, not to a currency.
        */
        if (($c_format == 2) && ($context->language->is_rtl == 1)) {
            $c_format = 4;
        }

        switch ($c_format) {
            /* X 0,000.00 */
            case 1:
                $ret = $c_char.$blank.number_format($price, $c_decimals, '.', ',');
                break;
            /* 0 000,00 X*/
            case 2:
                $ret = number_format($price, $c_decimals, ',', ' ').$blank.$c_char;
                break;
            /* X 0.000,00 */
            case 3:
                $ret = $c_char.$blank.number_format($price, $c_decimals, ',', '.');
                break;
            /* 0,000.00 X */
            case 4:
                $ret = number_format($price, $c_decimals, '.', ',').$blank.$c_char;
                break;
            /* X 0'000.00  Added for the switzerland currency */
            case 5:
                $ret = number_format($price, $c_decimals, '.', "'").$blank.$c_char;
                break;
        }
        if ($is_negative) {
            $ret = '-'.$ret;
        }
        if ($no_utf8) {
            return str_replace('€', chr(128), $ret);
        }
        return $ret;
    }

something like that

!!!!
and keep the PS_PRICE_DISPLAY_PRECISION at value = 2

 

to be true I would change also Cart.php (line 3052)
 

// from
// $shipping_cost = (float)Tools::ps_round((float)$shipping_cost, (Currency::getCurrencyInstance((int)$this->id_currency)->decimals * _PS_PRICE_DISPLAY_PRECISION_));

// to
 $shipping_cost = (float)Tools::ps_round((float)$shipping_cost, (Currency::getCurrencyInstance((int)$this->id_currency)->decimals ));

and

OrderInvoice.php (line 560)

// from
//    $row['ecotax_tax_incl'] = Tools::ps_round($row['ecotax_tax_excl'] + ($row['ecotax_tax_excl'] * $row['rate'] / 100), _PS_PRICE_DISPLAY_PRECISION_);
//    $row['ecotax_tax_excl'] = Tools::ps_round($row['ecotax_tax_excl'], _PS_PRICE_DISPLAY_PRECISION_);

// to  
    $row['ecotax_tax_incl'] = Tools::ps_round($row['ecotax_tax_excl'] + ($row['ecotax_tax_excl'] * $row['rate'] / 100), Currency::getCurrencyInstance((int)$this->id_currency)->decimals );
    $row['ecotax_tax_excl'] = Tools::ps_round($row['ecotax_tax_excl'], Currency::getCurrencyInstance((int)$this->id_currency)->decimals );

 

Edited by EvaF (see edit history)
Link to comment
Share on other sites

or just two lines 😉

Just add to case $add_zero. 😊

$add_zero = '';
if ($c_decimals == '1') {$add_zero = '0';} 

switch ($c_format)
		    {
			    case 1:
				    $ret = $c_char.$blank.number_format($price, $c_decimals, '.', ',').$add_zero;
				    break;
			    case 2:
				    $ret = number_format($price, $c_decimals, ',', ' ').$add_zero.$blank.$c_char;
				    break;
			    case 3:
				    $ret = $c_char.$blank.number_format($price, $c_decimals, ',', '.').$add_zero;
				    break;
			    case 4:
				    $ret = number_format($price, $c_decimals, '.', ',').$add_zero.$blank.$c_char;
				    break;
			    case 5:
				    $ret = $c_char.$blank.number_format($price, $c_decimals, '.', "'").$add_zero;
				    break;
		    }

 

Edited by Guest (see edit history)
Link to comment
Share on other sites

33 minutes ago, EvaF said:

My mistake - I  have fixed it in response above

Hello @EvaF and @Guest thanks for all your hell.
But with your income the total is wrong anyway, so lets see my image from cart.
All the math with total product with shippment (all without tax) is right but when the tax field comes it blows all :)
I'm in Portugal and in this client all product and shippment is 23% tax.
So the math is:
Total Tax = [Total products + shippement (without tax)] * 0.23 (and the problem is in here with round prestashop*)
Total Order = [Total products + shippement (without tax)] + Total Tax

* in math, rounds are made like (let's say 2 decimal)
1,234 it becames 1,23
1,235 it becames 1,24
So 3 decimal if is 5 or more, 2 decimal is up...and 3 decimal goes away
So 3 decimal if is 4 or less, 2 decimal stays the same...and 3 decimal goes away

If you have any ideias please help i'm all messed up :)
It also can be hardcoded, because i only will work with tax 23%

I've implemented @EvaF code and this is the result....
In tax field where is 16,20 it should be 16,17 because 70,30*0.23= 16,169 (and round it will be 16,17)

Captura de ecrã 2020-11-09, às 18.41.49.png

Edited by ruisonika (see edit history)
Link to comment
Share on other sites

in the case of tax try to check

configuration 'PS_ROUND_TYPE'

there are three options:

    const ROUND_ITEM = 1;
    const ROUND_LINE = 2;
    const ROUND_TOTAL = 3;

 

and results are rounded to PS_PRICE_DISPLAY_PRECISION places

 

 

 

 

Link to comment
Share on other sites

11 minutes ago, EvaF said:

in the case of tax try to check

configuration 'PS_ROUND_TYPE'

there are three options:

    const ROUND_ITEM = 1;
    const ROUND_LINE = 2;
    const ROUND_TOTAL = 3;

 

and results are rounded to PS_PRICE_DISPLAY_PRECISION places

 

 

 

 

I've sellect all one by one and the result is always wrong

i have no more ideias :(

Link to comment
Share on other sites

the number of decimals for round of tax is set at the line 1430 in the Cart.php

$compute_precision = $configuration->get('_PS_PRICE_COMPUTE_PRECISION_');

strange thing is, that I don't have set it.

if I am not wrong, it means that in my case  is  $compute_precision set to 0 (decimal places)

therefore check, plz your value of '_PS_PRICE_COMPUTE_PRECISION_'

and if it is not set in ps_configuration, set it

 

BTW - I am sorry - I don't still understand to how many decimal places do you want to round

Edited by EvaF (see edit history)
Link to comment
Share on other sites

I don't understand it either.
In the first post he writes that he wants to round it and then he writes that he does not want to round it.

VAT should always be a decimal number and the total amount may be rounded.

Then another item is added and this is called a penny call.
So there will be an amount either positive or negative.

Link to comment
Share on other sites

1 hour ago, Guest said:

I don't understand it either.
In the first post he writes that he wants to round it and then he writes that he does not want to round it.

VAT should always be a decimal number and the total amount may be rounded.

Then another item is added and this is called a penny call.
So there will be an amount either positive or negative.

In Portugal we work with prices with 2 decimal, and way to round it is the following,
lets work with this numbers
32,90
+ 4,50
_______
37,40 *0,23=8,602 (round it will be 8,60 but prestashop says that is 8,61; it only be 8,61 if the result it was 8,605 or higher)

May sense to you?

Link to comment
Share on other sites

If the digit in the next smallest place value is less than five (0, 1, 2, 3, or 4), you leave the digit you want to round to as-is. Any digits after that number (including the next smallest place value you just looked at) become zeros, or drop-off if they're located after the decimal point.
If the next smallest place value is greater than or equal to five (5, 6, 7, 8, or 9), you increase the value of the digit you're rounding to by one (+1). Just like before, any remaining digits before the decimal point become zeros, and any that are after the decimal point are dropped. 

Link to comment
Share on other sites

14 minutes ago, EvaF said:

ok, in your case should be
 


Configuration PS_PRICE_COMPUTE_PRECISION   = 2

Configuration PS_ROUND_TYPE                = 3

Configuration PS_PRICE_DISPLAY_PRECISION   = 2

and cart.php without my changes

plz check your values

 

 

 

?????? PS_PRICE_COMPUTE_PRECISION ??????

Why are you still nonsense here?

Test yourself in Prestashop 1.6.1.x to see if there are configurations that you still write here.

He is an ordinary user, he does not know the programming jargon and does not know where to change. It is better for such users to upload images.

This way you will confuse the user so much that he will not even know what he has already done, what changes he should return, etc.

SELECT * FROM `ps_configuration` WHERE `name` LIKE ('PS_PRICE_%') OR `name` LIKE ('PS_ROUND_%')

obrazek.thumb.png.55c0f75f01482728baee8570cc05f060.png

Link to comment
Share on other sites

yes I have written about it - I don't have "PS_PRICE_COMPUTE_PRECISION" in Configuration too...

but P1.6 works with it and rounds tax to PS_PRICE_COMPUTE_PRECISION

Cart.php line 1419

    public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products = null, $id_carrier = null, $use_cache = true)
    {
        ...
        $compute_precision = $configuration->get('_PS_PRICE_COMPUTE_PRECISION_');


            switch ($ps_round_type) {
                case Order::ROUND_TOTAL:
                    $products_total[$id_tax_rules_group.'_'.$id_address] += $price * (int)$product['cart_quantity'];
                    break;

                case Order::ROUND_LINE:
                    $product_price = $price * $product['cart_quantity'];
                    $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, $compute_precision);
                    break;

                case Order::ROUND_ITEM:
                default:
                    $product_price = /*$with_taxes ? $tax_calculator->addTaxes($price) : */$price;
                    $products_total[$id_tax_rules_group] += Tools::ps_round($product_price, $compute_precision) * (int)$product['cart_quantity'];
                    break;
            }
        }
        ...
        return Tools::ps_round((float)$order_total, $compute_precision);
    }

 

Link to comment
Share on other sites

Yes, I understand that now.

In phpMyAdmin -> SQL query:

INSERT INTO `ps_configuration` (`id_configuration`, `id_shop_group`, `id_shop`, `name`, `value`, `date_add`, `date_upd`) VALUES (NULL, NULL, NULL, 'PS_PRICE_COMPUTE_PRECISION', '2', '2020-11-10 00:00:00', '2020-11-10 00:00:00'); 
UPDATE `ps_configuration` SET `value` = '3' WHERE `name` = 'PS_ROUND_TYPE';
UPDATE `ps_configuration` SET `value` = '2' WHERE `name` = 'PS_PRICE_DISPLAY_PRECISION';

obrazek.thumb.png.52365e9e1f59a6055f0a2d23dc62f954.png

Of course, it is necessary to change the prefix ps_ to the prefix of the tables that are in the database.

Edited by Guest (see edit history)
Link to comment
Share on other sites

yes, I would a little bit modify your query - because I do not know anything about his configuration

INSERT IGNORE INTO `ps_configuration` (`id_configuration`, `id_shop_group`, `id_shop`, `name`, `value`, `date_add`, `date_upd`) VALUES (NULL, NULL, NULL, 'PS_PRICE_COMPUTE_PRECISION', '2', '2020-11-10 00:00:00', '2020-11-10 00:00:00');

 

Link to comment
Share on other sites

Hello @EvaF and @Guest i think is working like i wanna :)
In conclusion my Tool.php public static function displayPrice remains the same.
Cart.php i made the changes said by @EvaF and in phpmyadmin i made the query from @Guest and i've tested and for seems that all is fine.
Many Thanks to both.
You have many beers to drink in portugal :)

 

 

Link to comment
Share on other sites

to be true, it seems to me that in P1.6 are mixing
 

Configuraton::get('PS_PRICE_COMPUTE_PRECISION')   
// or Configuraton::get('_PS_PRICE_COMPUTE_PRECISION_')   

_PS_PRICE_COMPUTE_PRECISION_

Configuraton::get('PS_PRICE_DISPLAY_PRECISION')
// resp. _PS_PRICE_DISPLAY_PRECISION_

therefore I shoud repair my previous post

Cart.php (line 3052) and OrderInvoice.php (line 560) stays without changes

there is a danger of wrong result of rounding if

Configuraton::get('PS_PRICE_COMPUTE_PRECISION') <> Configuraton::get('PS_PRICE_DISPLAY_PRECISION')

Link to comment
Share on other sites

6 minutes ago, EvaF said:

to be true, it seems to me that in P1.6 are mixing
 


Configuraton::get('PS_PRICE_COMPUTE_PRECISION')   
// or Configuraton::get('_PS_PRICE_COMPUTE_PRECISION_')   

_PS_PRICE_COMPUTE_PRECISION_

Configuraton::get('PS_PRICE_DISPLAY_PRECISION')
// resp. _PS_PRICE_DISPLAY_PRECISION_

therefore I shoud repair my previous post

Cart.php (line 3052) and OrderInvoice.php (line 560) stays without changes

there is a danger of wrong result of rounding if

Configuraton::get('PS_PRICE_COMPUTE_PRECISION') <> Configuraton::get('PS_PRICE_DISPLAY_PRECISION')

Thanks @EvaF i had allready erase those changes.
Thanks for your support, this to me was an enigma :)

  • Haha 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...