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);
}
}
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.