Firefog
Firefog

Reputation: 3174

How to apply discount on shipping for a special product on woocommerce?

is there any way discount on shipping for a special product?

All USA shipping cost is $10.00 but if a product is in a cart the shipping cost will be $3.00 I have tried this using coupon code. How Can I check Billing /Shipping Country ?

But it set discount on total cost but I need to discount the shipping I also use different shipping classes.

What I am trying.

function shipping_costs_discounted( $rates, $package ){
 if ( is_admin() && ! defined( 'DOING_AJAX' ) )
    return $rates;

foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
        $product_id_in_cart = array( 1391193 );// this is product ID
        if( in_array( $cart_item['product_id'], $product_id_in_cart ) ) {   

            //Looking for the shipping classes
            $shipping_class = 'special-offer-discount'; // <=== Shipping class slug
            $discount_rate  = 1.46;
            $is_found       = false;
            // Loop through cart items and checking for the specific defined shipping class
            foreach( $package['contents'] as $cart_item ) {
                if( $cart_item['data']->get_shipping_class() == $shipping_class )
                    $is_found = true;
            }
            // Set shipping costs shipping class is found
            if( $is_found ){
                foreach ( $rates as $rate_key => $rate ){
                    $has_taxes = false;
                    // Targeting "flat rate"
                    if( 'flat_rate' === $rate->method_id  ){
                        $rates[$rate_key]->cost = $rate->cost - $discount_rate;

                        // Taxes rate cost (if enabled)
                        foreach ($rates[$rate_key]->taxes as $key => $tax){
                            if( $tax > 0 ){
                                $has_taxes = true;
                                $taxes[$key] = $tax - $discount_rate;
                            }
                        }
                        if( $has_taxes )
                            $rates[$rate_key]->taxes = $taxes;
                    }
                }
            }
            return $rates;
        }
    }
}
add_filter('woocommerce_package_rates', 'shipping_costs_discounted', 10, 2);

Upvotes: 0

Views: 281

Answers (1)

silver
silver

Reputation: 5311

Assuming you'll modify the woocommerce_package_rates filter, all the items in cart are in $package variables inside contents key, so you can simply loop through it and pull all the id for checking if the product you want are in there.

Destination info are also in the $package variable inside destination keys, it contains full shipping address including country;

this is an example json output of $package variable

{
    "contents": {
        "044a23cadb567653eb51d4eb40acaa88": {
            "key": "044a23cadb567653eb51d4eb40acaa88",
            "product_id": 2754,
            "variation_id": 0,
            "variation": [],
            "quantity": 2,
            "data_hash": "b5c1d5ca8bae6d4896cf1807cdf763f0",
            "line_tax_data": {
                "subtotal": [],
                "total": []
            },
            "line_subtotal": 35.9,
            "line_subtotal_tax": 0,
            "line_total": 35.9,
            "line_tax": 0,
            "data": {}
        },
        "0fc170ecbb8ff1afb2c6de48ea5343e7": {
            "key": "0fc170ecbb8ff1afb2c6de48ea5343e7",
            "product_id": 2800,
            "variation_id": 0,
            "variation": [],
            "quantity": 1,
            "data_hash": "b5c1d5ca8bae6d4896cf1807cdf763f0",
            "line_tax_data": {
                "subtotal": [],
                "total": []
            },
            "line_subtotal": 107.95,
            "line_subtotal_tax": 0,
            "line_total": 107.95,
            "line_tax": 0,
            "data": {}
        }
    },
    "contents_cost": 143.85,
    "applied_coupons": [],
    "user": {
        "ID": 1
    },
    "destination": {
        "country": "US",
        "state": "",
        "postcode": "",
        "city": "Pine Bluff",
        "address": "",
        "address_1": "",
        "address_2": ""
    },
    "cart_subtotal": 143.85,
    "rates": {
        "flat_rate:3": {}
    }
}

So with that info, you can do something like this to modify the Shipping Cost and Shipping label

add_filter('woocommerce_package_rates', '_shipping_cost_product_ID', 100, 2);
function _shipping_cost_product_ID( $rates, $package ){

    // duh
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return $rates;

    // The ID of the product you want to modify shipping cost if found in cart
    $discounted_product_id = 2800;

    // Get all the product IDs added in cart and put them in array
    $ids_in_cart = [];
    foreach ( $package['contents'] as $key => $item ) {
        $ids_in_cart[] = $item['product_id'];
    }

    // loop through each shipping rates
    foreach ( $rates as $rate_key => $rate ){

        $has_taxes = false;

        // Only modify shipping if all conditions below are meet
        if( 
            'flat_rate' === $rate->method_id // if shipping method is "Flat RATE"
            && ( isset($package['destination']['country'] ) && $package['destination']['country'] == 'US' )  // if country is US
            && in_array($discounted_product_id, $ids_in_cart )//if $discounted_product_id is in cart
            ) {

            $rates[$rate_key]->label = 'Cool Shipping'; // Modify Shipping Name
            $rates[$rate_key]->cost = 3.00; // Modify Shiping Cost

            //Taxes rate cost (if enabled)
            $taxes = [];
            foreach ($rates[$rate_key]->taxes as $key => $tax){
                if( $rates[$rate_key]->taxes[$key] > 0 ){
                    $initial_tax_cost = $new_tax_cost = $rates[$rate_key]->taxes[$key];
                    $tax_rate    = $initial_tax_cost / $initial_cost;
                    $taxes[$key] = $new_cost * $tax_rate;
                    $has_taxes   = true; 
                }
            }
            if( $has_taxes ) $rates[$rate_key]->taxes = $taxes;
        }
    }
    return $rates;
}

Upvotes: 2

Related Questions