3
votes

I'm trying to specify 2 different Flat rates shipping methods costs without using a plugin:

  • If there is a product in the cart from only one Vendor, the Flat rate shipping cost needs to be £19.
  • If there are multiple products in the cart from more than one Vendor, the Flat rate shipping cost needs to be £39.

I have tried various plugins, but they focus on shipping rates based on size, weight, quantity, location, category, but not Attributes or Terms.

I have an Attribute named Vendor with 8 Terms. Each Term is a different Vendor/supplier.

Here's the type of PHP logic I would like to implement:

if product attribute term quantity = 1

then flat rate = £19

else

if product attribute term quantity > 1

then flat rate = £39

How can I change this "Flat rate" shipping method cost when there is more than 1 attribute Vendor terms in cart?

1

1 Answers

2
votes

This process needs 2 steps: some code and some settings…

1) CODE - You can use a custom function hooked in woocommerce_package_rates filter hook, targeting the "Flat rate" shipping method when cart items are from more than 1 vendor:

add_filter( 'woocommerce_package_rates', 'custom_flat_rate_cost_calculation', 10, 2 );
function custom_flat_rate_cost_calculation( $rates, $package )
{

    // SET BELOW your attribute slug… always begins by "pa_"
    $attribute_slug = 'pa_vendor'; // (like for "Color" attribute the slug is "pa_color")


    // Iterating through each cart item to get the number of different vendors
    foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {

        // The attribute value for the current cart item
        $attr_value = $cart_item[ 'data' ]->get_attribute( $attribute_slug );

        // We store the values in an array: Each different value will be stored only one time
        $attribute_values[ $attr_value ] = $attr_value;
    }
    // We count the "different" attribute values stored
    $count = count($attribute_values);

    // Iterating through each shipping rate
    foreach($rates as $rate_key => $rate_values){
        $method_id = $rate_values->method_id;
        $rate_id = $rate_values->id;

        // Targeting "Flat Rate" shipping method
        if ( 'flat_rate' === $method_id ) {
            // For more than 1 vendor (count)
            if( $count > 1 ){
                // Get the original rate cost
                $orig_cost = $rates[$rate_id]->cost;
                // Calculate the new rate cost
                $new_cost = $orig_cost + 20; // 19 + 20 = 39
                // Set the new rate cost
                $rates[$rate_id]->cost = $new_cost;
                // Calculate the conversion rate (for below taxes)
                $conversion_rate = $new_cost / $orig_cost;
                // Taxes rate cost (if enabled)
                foreach ($rates[$rate_id]->taxes as $key => $tax){
                    if( $rates[$rate_id]->taxes[$key] > 0 ){
                        $new_tax_cost = number_format( $rates[$rate_id]->taxes[$key]*$conversion_rate, 2 );
                        $rates[$rate_id]->taxes[$key] = $new_tax_cost; // set the cost
                    }
                }
            }
        }
    }
    return $rates;
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

This code is tested with woocommerce version 3+ and works

2) SETTINGS - Once the above code has been saved in the function.php file of your active theme, you will need to set (for all your shipping zones) the "Flat rate" shipping method cost to 19 (£19) (and save).

IMPORTANT: To refresh Shipping method caches you will need to disable "flat rate" then save, and enable back "flat rate" then save.

Now This should work for you as expected.