0

I have been conducting extensive research on rounding at the cart item subtotal level, but I have not been able to find a solution.

What I want to do is to round the product subtotal after discout applied. Then caculate cart total and total by adding all product subtotal together.

I have tried different hooks such as:

  1. woocommerce_before_calculate_totals - This hook only allows me to modify the product price.
  2. woocommerce_cart_product_subtotal (filter) - This hook only affects the display of the cart item subtotal; it does not alter the calculation of the cart subtotal and total.
  3. woocommerce_calculate_totals - This hook only allows me to modify calculations based on the product price and quantity, and it is not directly related to the cart item subtotal.

If you have any suggestions or solutions, I would greatly appreciate your assistance. Thank you!

Cart product subtotal rounding

  • You should only round the display in cart and checkout, then when order is submitted, you will round first your items using [`woocommerce_checkout_create_order_line_item`](https://github.com/woocommerce/woocommerce/blob/release/8.0/plugins/woocommerce/includes/class-wc-checkout.php#L549) and also all other items hooks for 'tax', 'fee', 'shipping', 'coupon'… then to finish you will adjust totals (if needed) in [`woocommerce_checkout_create_order`](https://github.com/woocommerce/woocommerce/blob/release/8.0/plugins/woocommerce/includes/class-wc-checkout.php#L446C16-L446C49)... A nightmare :) – LoicTheAztec Aug 23 '23 at 21:01
  • Thank you for your advice. Now I can confirm that the cart item subtotal has nothing to do with the cart total and total calculation. If I need to do rounding with an individual item subtotal and calculate the total based on the rounding subtotal I need to do it with hook woocommerce_checkout_create_order line item. Am I correct? – Kelvin Winter Aug 24 '23 at 08:22
  • Just try… All related hooks are located in `WC_Checkout Class`, starting from `create_order()` method. – LoicTheAztec Aug 24 '23 at 08:48
  • Thanks. So all the action and filter in class-wc-cart.php is only for cart display. Woocommerce calculate all price and total during the checkout process again? – Kelvin Winter Aug 24 '23 at 10:34
  • WC_Cart => cart and checkout | | | | WC_Checkout => Orders – LoicTheAztec Aug 24 '23 at 10:44
  • For cart and checkout display, also look in the WooCommerce templates located in "cart" and "checkout" folders. – LoicTheAztec Aug 24 '23 at 10:46
  • 1
    Thank you very much for your information. It seems that not an easy task. – Kelvin Winter Aug 26 '23 at 15:01
  • I found a possible solution for this, would you please take a look and give me some advice? Thanks. – Kelvin Winter Aug 28 '23 at 18:40
  • Down below, the answer I posted. Thanks. – Kelvin Winter Aug 28 '23 at 19:23

1 Answers1

0

After some trials, I came up with this:

add_action('woocommerce_before_calculate_totals', 'my_woocommerce_calculate_totals', 10, 1);

function my_woocommerce_calculate_totals($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
    return;
}

// Loop over $cart items
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
    // Get line specific data
    $itemQuantity = $cart_item['quantity'];
    $productObject = $cart_item['data']; // Get the product object
    $productPrice = $productObject->get_price();
    $regular_price = $productObject ->get_regular_price();
    
    // Calculate new price per item
    $discount = ($regular_price - $productPrice) / $regular_price;
    $new_price = (round($productPrice * $itemQuantity) / $itemQuantity) / (1 - $discount);

    // Set new price
    $productObject->set_price($new_price);
}
}

Example: Product regular price $750, quantity 5, discount 15%Off.

Normal calculation: Item subtotal = $750 x 0.85 x 5 = $3187.5

Modified calculation:

New Price = round($750 x 0.85 x 5) / 5 / 0.85 = 750.1176471.

Item subtotal = $750.1176471 x 0.85 x 5 = $3188.

The theory is to calculate item subtotals and round them to the nearest integers. Then re-calculate the new price from the rounded item subtotals. I did some tests and this function shows correct rounded subtotals and totals. However, the product price will be modified.

Any comment on this solution? Will it cause any problems? Thank you very much in advance.

  • Yes, that is a valid solution, if it fit your needs. But you will have to add a hooked function in `woocommerce_cart_item_price` filter hook and make the same calculations but for the displayed price in mini cart, a bit like in [this answer](https://stackoverflow.com/questions/76575570/woocommerce-hooks-to-increase-some-product-prices-conditionally/76577941#76577941) for this hook. – LoicTheAztec Aug 28 '23 at 20:24