phpwordpresswoocommercecategoriescustom-taxonomy

Add shipping cost on per product based on category and country


On my WooCommerce website, I have here some code that is working but not so well.

Calculation on countries is working fine, but when I added the categories the prices is not correct.

Here is my code:

add_filter( 'woocommerce_get_discounted_price', 'calculate_discounted_price', 10, 2 );
add_filter( 'woocommerce_cart_item_subtotal', 'display_discounted_price', 10, 2 );

function calculate_discounted_price( $price, $values ) {
    global $woocommerce, $product;

    $countryArray = array( 'AL', 'AD', 'AT', 'BY', 'BE', 'BA', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FO', 'FI', 'FR', 'DE', 'GI', 'GR', 'HU', 'IS', 'IE', 'IM', 'IT', 'RS', 'LV', 'LI', 'LT', 'LU', 'MK', 'MT', 'MD', 'MC', 'ME', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'SM', 'RS', 'SK', 'SI', 'ES', 'SE', 'CH', 'UA', 'VA', 'RS' );
    $catArray = array('handbags','kids','hats');


                if( $woocommerce->customer->get_shipping_country() == 'GB' ) {

                    foreach ( $woocommerce->cart->cart_contents as $product ) :
                    if ( has_term( $catArray, 'product_cat', $product['product_id'] ) ) {
                        $price += 4.50;
                    } else {
                        $price += 8.50; 
                    }
                    endforeach;             

                } elseif( in_array($woocommerce->customer->get_shipping_country(), $countryArray) ) {

                    foreach ( $woocommerce->cart->cart_contents as $product ) :
                    if ( has_term( $catArray, 'product_cat', $product['product_id'] ) ) {
                        $price += 4.50;
                    } else {
                        $price += 12.50;    
                    }
                    endforeach;

                } else {

                    foreach ( $woocommerce->cart->cart_contents as $product ) :
                    if ( has_term( $catArray, 'product_cat', $product['product_id'] ) ) {
                        $price += 8.50;
                    } else {
                        $price += 18.50;    
                    }
                    endforeach;
                }

    return $price;
}

function display_discounted_price( $values, $item ) {
    return wc_price( $item[ 'line_total' ] ).'<br>incl. shipping';
}

When I remove all the foreach statement and leave only the country condition it works fine, the foreach loop is somehow causing the problem.

Some help on this, will very appreciated.

Thanks.


Solution

  • You don't need the cart foreach loop to get the product ID, as you will see below. I haven't solved your problem of strange displayed prices as it seems coming from the product categories condition. I have to test that further, but this unfinished code will help you to understand what are the arguments in the first hooked function:

    add_filter( 'woocommerce_get_discounted_price', 'calculate_discounted_price', 10, 3 );
    function calculate_discounted_price( $price, $cart_item, $cart_object ) {
    
        $country_arr = array( 'AL', 'AD', 'AT', 'BY', 'BE', 'BA', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FO', 'FI', 'FR', 'DE', 'GI', 'GR', 'HU', 'IS', 'IE', 'IM', 'IT', 'RS', 'LV', 'LI', 'LT', 'LU', 'MK', 'MT', 'MD', 'MC', 'ME', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'SM', 'RS', 'SK', 'SI', 'ES', 'SE', 'CH', 'UA', 'VA', 'RS' );
    
        $cats_arr = array('handbags','kids','hats');
    
        // ONLY for logged users (I think)
        $user_ship_country = WC()->customer->get_shipping_country();
    
    
        $product_id = $cart_item['product_id'];
    
        if( $user_ship_country == 'GB' ) {
    
            if ( has_term( $cats_arr, 'product_cat', $product_id ) )
                $price += 4.50;
            else
                $price += 8.50;
    
        } elseif( in_array($user_ship_country, $country_arr) ) {
    
            if ( has_term( $cats_arr, 'product_cat', $product_id ) )
                $price += 4.50;
            else
                $price += 12.50;
    
        } else {
    
            if ( has_term( $cats_arr, 'product_cat', $product_id ) )
                $price += 8.50;
            else
                $price += 18.50;
    
        }
    
        return $price;
    }
    
    add_filter( 'woocommerce_cart_item_subtotal', 'display_discounted_price', 10, 2 );
    function display_discounted_price( $values, $item ) {
        return wc_price( $item[ 'line_total' ] ).'<br>incl. shipping';
    }
    

    Also WC()->customer->get_shipping_country(); will only work for log gin customers (I think)…

    Hope this will help you a bit.

    BUT For shipping additional costs, I think that you are not using the right hooks…