Search code examples
phpwordpresswoocommercehook-woocommercefee

How to Combine Different Woocommerce Fees into One Name?


I'm setting up California Redemption value fees for my site. The code that I have found on here works, however I would like for the different fees to be combined under the same name, which would just be "C.R.V." but still count the appropriate fees based on the different products in the cart. Example: One 5 Cent CRV item and one 10 Cent CRV item in the cart will currently be displayed on two separate lines. I would like an outcome of just "C.R.V. - 0.15c"

Currently Displayed as:

Using code from the answer to this page

Code that I am using:

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

    // Settings (multiple settings arrays can be added/removed if desired)
    $settings = array(
        array(
            'product_id'    => array( 11891, 11893 ),
            'amount'        => 0.05,
            'name'          => __( '5 Cent C.R.V.', 'woocommerce' ),
            'total_amount'  => 0,
        ),
        array(
            'product_id'    => array( 11892 ),
            'amount'        => 0.10,
            'name'          => __( '10 Cent C.R.V.', 'woocommerce' ),
            'total_amount'  => 0,
        ),
        array(
            'product_id'    => array( 825 ),
            'amount'        => 0.20,
            'name'          => __( '20 Cent CRV', 'woocommerce' ),
            'total_amount'  => 0,
        ),
    );
    
    // Loop through cart contents
    foreach ( $cart->get_cart_contents() as $cart_item ) {      
        // Get product id
        $product_id = $cart_item['product_id'];
        
        // Get quantity
        $quantity = $cart_item['quantity'];
        
        // Loop trough settings array (determine total amount)
        foreach ( $settings as $key => $setting ) {
            // Search for the product ID
            if ( in_array( $product_id, $settings[$key]['product_id'] ) ) {
                // Addition
                $settings[$key]['total_amount'] += $setting['amount'] * $quantity;
            }
        }       
    }
    
    // Loop trough settings array (output)
    foreach ( $settings as $setting ) {
        // Greater than 0
        if ( $setting['total_amount'] > 0 ) {
            // Add fee
            $cart->add_fee( $setting['name'], $setting['total_amount'], false );    
        }
    }
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );

I have tried renaming all of the fees to just "C.R.V." but then the cart will only display and count one fee. I apologize if this is very simple or staring at me in the face but I am extremely new to any sort of coding. Any help is very appreciated!


Solution

  • If I have well understood, the following will apply a merged 'CRV' fee for defined products, based on your settings.

    I have simplified your code, try:

    add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );
    function action_woocommerce_cart_calculate_fees( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        // Settings: amount / product Ids
        $settings = array(
            '0.05' => array( 11891, 11893 ),
            '0.1'  => array( 11892 ),
            '0.2'  => array( 825 ),
        );
    
        $total_amount = 0; // Initializing
        
        // Loop through cart items
        foreach ( $cart->get_cart() as $item ) {
            // Loop trough settings array
            foreach ( $settings as $amount => $product_ids ) {
                // Search for the product ID
                if ( in_array( $item['product_id'], $product_ids) ) {
                    $total_amount += floatval($amount) * intval($item['quantity']); // Add to total amount
                }
            }
        }
    
        if ( $total_amount > 0 ) {
            $cart->add_fee( __( 'CRV', 'woocommerce' ), $total_amount, false ); 
        }
    }
    

    It should work.


    Addition - Target with product Categories or Tags terms:

    To target product categories or product tags, replace your in settings the product IDs arrays with desired term slugs arrays (for each array).

    Then replace in the code:

    if ( in_array( $item['product_id'], $product_ids) ) {
    

    with (for product categories):

    if ( has_term( $product_ids, 'product_cat', $item['product_id']) ) {
    

    or (for product tags):

    if ( has_term( $product_ids, 'product_tag', $item['product_id']) ) {