Use 2 decimals for discount amount in Woocommerce with 0 decimals settings

I am using 0 decimals under wc-settings&tab=general which is working fine for my usecase. But now adding a discount for a specific payment method which is set to 10 percent at the moment. For an 12 usd item it rounds the discount value to 1 - which reuslt in an a total of 11 instead of 10.8 due to the 0 decimals settings mentioned before. The closest i came up with was the following filter, but resultet in shipping cost going from 23 to 23.23 usd too. Any idea how to apply the 2 decimals only to the discount amount without interfering elsewhere? // Change woo settings from 0 at the moment in backend to 2 decimals for wallet payment add_filter( 'wc_get_price_decimals', 'custom_price_decimals_for_wallet_s0dgPHq2',10,1); function custom_price_decimals_for_wallet_s0dgPHq2( $decimals ) { // Check if we are on the front-end and WooCommerce session is available if ( !is_admin() && WC()->session && isset(WC()->session->chosen_payment_method) ) { // Only change decimal places if the chosen payment method is wallet if ( WC()->session->chosen_payment_method === 'wallet' ) { // Set to 2 decimals for wallet payments $decimals = 2; return $decimals; } // Return the default value for other cases return $decimals; } } Here my discount code: add_filter( 'woocommerce_cart_calculate_fees', 'discount_based_on_payment_method_e643e', 10, 1 ); function discount_based_on_payment_method_e643e( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( ! ( is_checkout() && ! is_wc_endpoint_url() ) ) return; $targeted_payment_method = 'wallet'; // Here define the desired payment method global $abc_options; $wallet_pay_discount_amount = $abc_options['wallet_payment_discount_amount_value']; $wallet_pay_discount_amount_formated = $wallet_pay_discount_amount / 100; // results in 0.10 for 10% and so on if( WC()->session->get('chosen_payment_method') === $targeted_payment_method ) { $cart_subtotal = WC()->cart->get_subtotal(); $discount = $cart_subtotal * $wallet_pay_discount_amount_formated; $fee_description = '~ ' . $wallet_pay_discount_amount . '% ' . __('Discount Wallet Payment', 'nm-ffk'); $cart->add_fee($fee_description, -$discount); } }

Comment (1)

Jese Leos

August 10, 2024

Verified user

To change only the fee displayed amount decimals in WooCommerce checkout page, use the following code replacement: // Add a negative fee (discount) in Checkout page add_action( 'woocommerce_cart_calculate_fees', 'discount_based_on_payment_method_e643e', 10, 1 ); // Action hook! function discount_based_on_payment_method_e643e( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; if ( ! ( is_checkout() && ! is_wc_endpoint_url() ) ) return; $payment_id = 'wallet'; // The targeted payment method ID if( WC()->session->get('chosen_payment_method') === $payment_id ) { global $abc_options; $discount_rate = $abc_options['wallet_payment_discount_amount_value']; $discount_amount = WC()->cart->get_subtotal() * $discount_rate / 100; $fee_description = '~ ' . $discount_rate . '% ' . __('Discount Wallet Payment', 'nm-ffk'); $cart->add_fee($fee_description, -$discount_amount); } } // Update checkout on payment method change add_action( 'woocommerce_checkout_init', 'update_checkout_on_payment_method_change' ); function update_checkout_on_payment_method_change() { wc_enqueue_js("$('form.checkout').on( 'change', 'input[name=payment_method]', function(){ $(document.body).trigger('update_checkout'); });"); } // Display 2 decimals for fees amounts on Checkout page add_filter( 'woocommerce_cart_totals_fee_html', 'filter_woo_cart_totals_fee_html', 10, 2 ); function filter_woo_cart_totals_fee_html( $fee_html, $fee ){ $args = array( 'decimals' => 2 ); return WC()->cart->display_prices_including_tax() ? wc_price( $fee->total + $fee->tax, $args ) : wc_price( $fee->total, $args ); } Code goes in functions.php file of your child theme (or in a plugin). Tested and works with WooCommerce Checkout Legacy (shortcode). Untested with new Checkout Block. Addition: For customer orders and email notifications (not possible in admin order): // Display 2 decimals for fees amounts on Customer orders and email notifications add_filter( 'woocommerce_get_order_item_totals', 'filter_woo_order_item_fee_totals', 10, 3 ); function filter_woo_order_item_fee_totals( $total_rows, $order, $tax_display ){ // Loop through total rows foreach ( $total_rows as $key => $data ) { // Loop through order fees foreach ( $order->get_fees() as $id => $fee ) { if( $key === 'fee_'.$id ) { $args = array( 'currency' => $order->get_currency(), 'decimals' => 2 ); $total_rows[$key]['value'] = wc_price( 'excl' === $tax_display ? (float) $fee->get_total() : (float) $fee->get_total() + (float) $fee->get_total_tax(), $args ); } } } return $total_rows; } Code goes in functions.php file of your child theme (or in a plugin). It should work.

You’ll be in good company