Miguel Angel Martinez
Miguel Angel Martinez

Reputation: 206

Change number of decimals in Woocommerce cart totals

In Woocommerce, I've set the number of decimal to 7 on in Woocommerce general settings, so I can display the product price like this $0.0453321.

I'm wondering if I can set/round the cart total to only 2 decimals (something like this $2.34)?

Upvotes: 2

Views: 10082

Answers (4)

Kristián Filo
Kristián Filo

Reputation: 865

The accepted answer changes the number of decimals globally on cart page, checkout page and thankyou page using wc_get_price_decimals filter. For my use case, the checkout page condition is OK (since there are no cart item prices displayed), but for cart page I only need 2 decimals in cart totals, not in cart items.

To keep 3 decimals (from WC settings) in cart items, and display 2 decimals for cart totals, you can add and then remove the desired filter in specific cart page actions:

// Change display to 2 decimals before cart totals
function start_two_decimal_display() {
    add_filter( 'wc_get_price_decimals', function() { return 2; }, 20 );
}
add_action( 'woocommerce_before_cart_totals', 'start_two_decimal_display', 20 );

// Change display back to 3 decimals after cart totals
function end_two_decimal_display() {
    add_filter( 'wc_get_price_decimals', function() { return 3; }, 20 );
}
add_action( 'woocommerce_after_cart_totals', 'end_two_decimal_display', 20 );

You can utilize the same approach for different sections as well, using different actions.

Upvotes: 0

LoicTheAztec
LoicTheAztec

Reputation: 253784

The correct way is to change just the number of allowed decimals for cart and checkout pages only:

add_filter( 'wc_get_price_decimals', 'change_prices_decimals', 20, 1 );
function change_prices_decimals( $decimals ){
    if( is_cart() || is_checkout() )
        $decimals = 2;
    return $decimals;
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.


To set the dispayed cart gran total with 2 decimals use this instead (for Woocommerce 3.3+ only):

add_filter( 'woocommerce_cart_tax_totals', 'change_decimals_cart_tax_totals', 20, 2 );
function change_decimals_cart_tax_totals( $tax_totals, $cart ){
    $decimals = array('decimals' => 2);

    $taxes      = $cart->get_taxes();
    $tax_totals = array();

    foreach ( $taxes as $key => $tax ) {
        $code = WC_Tax::get_rate_code( $key );

        if ( $code || $key === apply_filters( 'woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated' ) ) {
            if ( ! isset( $tax_totals[ $code ] ) ) {
                $tax_totals[ $code ] = new stdClass();
                $tax_totals[ $code ]->amount = 0;
            }
            $tax_totals[ $code ]->tax_rate_id       = $key;
            $tax_totals[ $code ]->is_compound       = WC_Tax::is_compound( $key );
            $tax_totals[ $code ]->label             = WC_Tax::get_rate_label( $key );
            $tax_totals[ $code ]->amount           += wc_round_tax_total( $tax );
            $tax_totals[ $code ]->formatted_amount  = wc_price( wc_round_tax_total( $tax_totals[ $code ]->amount ), $decimals );
        }
    }

    if ( apply_filters( 'woocommerce_cart_hide_zero_taxes', true ) ) {
        $amounts    = array_filter( wp_list_pluck( $tax_totals, 'amount' ) );
        $tax_totals = array_intersect_key( $tax_totals, $amounts );
    }
    return $tax_totals;
}

add_filter( 'woocommerce_cart_totals_order_total_html', 'change_decimals_cart_totals_order_total_html', 20, 1 );
function change_decimals_cart_totals_order_total_html( $formatted_price ){
    $decimals = array('decimals' => 2);

    $value = '<strong>' . wc_price( WC()->cart->get_total('edit'), $decimals ) . '</strong> ';

    // If prices are tax inclusive, show taxes here.
    if ( wc_tax_enabled() && WC()->cart->display_prices_including_tax() ) {
        $tax_string_array = array();
        $cart_tax_totals  = WC()->cart->get_tax_totals();

        if ( get_option( 'woocommerce_tax_total_display' ) == 'itemized' ) {
            foreach ( $cart_tax_totals as $code => $tax ) {
                $tax_string_array[] = sprintf( '%s %s', $tax->formatted_amount, $tax->label );
            }
        } elseif ( ! empty( $cart_tax_totals ) ) {
            $tax_string_array[] = sprintf( '%s %s', wc_price( WC()->cart->get_taxes_total( true, true ), $decimals ), WC()->countries->tax_or_vat() );
        }

        if ( ! empty( $tax_string_array ) ) {
            $taxable_address = WC()->customer->get_taxable_address();
            $estimated_text  = WC()->customer->is_customer_outside_base() && ! WC()->customer->has_calculated_shipping()
                ? sprintf( ' ' . __( 'estimated for %s', 'woocommerce' ), WC()->countries->estimated_for_prefix( $taxable_address[0] ) . WC()->countries->countries[ $taxable_address[0] ] )
                : '';
            $value .= '<small class="includes_tax">' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) . $estimated_text ) . '</small>';
        }
    }
    return $value;
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

You can't really round the prices in cart totals appart. If you do it with different hooks, you will get calculation errors. My code is just changing the number of decimals on displayed formatted prices and will not alter the calculations on real prices…

Related: Change number of decimals on Woocommerce displayed cart subtotal

Upvotes: 6

frezq
frezq

Reputation: 702

In my case I needed to keep 3 decimal places "visible" throughout the site but approximate only the grand total to 2 decimal places (with a zero for the third decimal place) because my payment gateway accepted only 2 significant digits after the decimal.

Prices displayed as: 0.336
Taxes: 0.017
But grand total needed to be: 0.350 (instead of 0.353)

I ended up not using the code because it was so horrific but you can say it was a mental excercise:

add_filter( 'wc_get_price_decimals', 'change_prices_decimals', 20, 1 );
function change_prices_decimals( $decimals ){

    if( is_cart() || is_checkout() )
    {
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,0);
        $length = count($trace);
        for ($i = 0; $i < $length; $i++)
        {
            if($trace[$i]["function"] == "set_total"){
                $decimals = 2;
                return $decimals;
            }
        }
    }

    return $decimals;
}

Upvotes: 0

dipmala
dipmala

Reputation: 2011

If you want to change cart total only at cart and checkout page then you need to copy template in your theme

First copy 2 files from woocommerce plugin template to your theme .

1) Copy plugins\woocommerce\templates\cart\cart-totals.php to your-theme-folder\woocommerce\cart\cart-totals.php

2) Copy plugins\woocommerce\templates\checkout\review-order.php to your-theme-folder\woocommerce\checkout\review-order.php

And in both files find the wc_cart_totals_order_total_html() comment this code and put below code instead.

  $args=array('decimals'=> 2);
  echo  wc_price(WC()->cart->total,$args); 

This code is tested and its working fine.Hope it will help you as well.

Upvotes: 0

Related Questions