How to avoid calculation of a duplicate subsidy when there is a bundle product in WooCommerce cart?

With the code below, I calculate and displays the total subsidies amount based on cart item shipping class and quantity: /** * Utility function: Get shipping class subsidy amount * * @return float */ function get_shipping_class_subsidy_amount( $shipping_class ) { // return a float number for '12-50' case if ( false !== strpos($shipping_class, '12-50') ) { return 12.5; } // Extract the integer from the slug else { return preg_replace('/\D/', '', $shipping_class); } } /** * Utility function: Get total subsidies amount * * @return float */ function get_total_subsidies( $cart_items ){ $total_subsidy = 0; // Initializing // Loop through cart items foreach ( $cart_items as $item ){ $subsidy = (float) get_shipping_class_subsidy_amount( $item['data']->get_shipping_class() ); $price = get_post_meta($values['product_id'] , '_price', true); if ( $subsidy > 0 ) { $total_subsidy += $item['quantity'] * $subsidy; } } return $total_subsidy; } /** * Display HTML formatted total subsidies amount in classic cart and checkout pages. * Hooked function. */ function display_total_subsidies() { if ( $total_subsidy = get_total_subsidies( WC()->cart->get_cart() ) ) { echo '<tr class="subsidies"> <th>' . esc_html__( 'Subsidies', 'woocommerce' ) . '</th> <td data-title="' . esc_html__( 'Subsidies', 'woocommerce' ) . '">' . wc_price($total_subsidy) . '</td> </tr>'; } } add_action ( 'woocommerce_cart_totals_before_shipping', 'display_total_subsidies', 10 ); // for Cart page add_action ( 'woocommerce_review_order_before_shipping', 'display_total_subsidies', 10 ); // for Checkout page The problem is that the cart item subsidy amount is obtained twice when it's a bundle product, as it takes into account the bundled product itself and it's products components. But the calculation in the label is correct.

Comment (1)

Jese Leos

August 19, 2024

Verified user

Bundle products in WC are treated as separate line items for both the parent bundle and its individual components, which means that in the current loop in the get_total_subsidies function may double-count the subsidy for bundled products. You can try to apply the subsidy calculation to the child components of a bundle to your code. function get_total_subsidies( $cart_items ){ $total_subsidy = 0; // Initializing // Loop through cart items foreach ( $cart_items as $item_key => $item ){ // Skip child items of bundled products if ( isset( $item['bundled_by'] ) && ! empty( $item['bundled_by'] ) ) { continue; } $subsidy = (float) get_shipping_class_subsidy_amount( $item['data']->get_shipping_class() ); if ( $subsidy > 0 ) { $total_subsidy += $item['quantity'] * $subsidy; } } return $total_subsidy; }

You’ll be in good company