1

WP 5.3.3

I need to change shipping cost programmatically, after order creation.

This code doesn't affect:

add_action('woocommerce_new_order', 'custom_shipping_costs',  1, 1);
function custom_shipping_costs($order_id)
{
    $order = wc_get_order($order_id);
    $shippingItems = (array) $order->get_items('shipping');
    foreach ($shippingItems as $item) {
        $item->cost = 0;
    }
    $order->save();
}

Some help please?

Update 1:

It's important that I need to change shipping price in every n-th order. Something like this:

if ($order_id % 10 == 0) {
    // change shipping price for every 10-th order
}

Update 2 (the solution):

Thanks @LoicTheAztec - the solution is based on his answer, with a little changes:

  1. set_option -> update_option
  2. set_total_tax throws an error, so I changed this part a bit (This thread helped me).

The final code (goes in functions.php file of your active child theme or active theme):

// Set a count based on placed orders for shipping items cost change
add_action('woocommerce_checkout_create_order', 'action_wc_checkout_create_order', 10, 2);
function action_wc_checkout_create_order($order, $data)
{
    // get $order count for shipping item change
    $orders_count = (int) get_option('wc_orders_count_for_shipping');

    // Increase count for next order (starting count at 2 as this hook is triggered after shipping items hook)
    update_option('wc_orders_count_for_shipping', $orders_count > 0 ? $orders_count + 1 : 2);
}

// Set shipping cost to zero every 10-th orders when order is placed
add_action('woocommerce_checkout_create_order_shipping_item', 'action_wc_checkout_create_order_shipping_item', 10, 4);
function action_wc_checkout_create_order_shipping_item($item, $package_key, $package, $order)
{
    $orders_count = (int) get_option('wc_orders_count_for_shipping');

    // Every 10-th orders 
    if ($orders_count > 0 && ($orders_count % 10) === 0) {
        $item->set_total(0);
        $item->set_taxes(['total' => '0']);
        //$item->set_total_tax('0');
        $item->save();
        $order->calculate_totals();
    }
}
aynber
  • 22,380
  • 8
  • 50
  • 63
Alex Skutin
  • 75
  • 1
  • 6

2 Answers2

2

First as Order IDs are not sequential because they are based on the post ID that is used also on Wordpress pages, posts and all other custom posts like Woocommerce products and coupons. So we need to enable a sequential count on your WooCommerce orders to make changes on every 10th orders.

The following will set shipping costs to zero every 10th orders, when order is placed before saving order data to database:

// Set a count based on placed orders for shipping items cost change
add_action( 'woocommerce_checkout_create_order', 'action_wc_checkout_create_order', 10, 2 );
function action_wc_checkout_create_order( $order, $data ) {
    $orders_count = (int) get_option('wc_orders_count_for_shipping'); // get $order count for shipping item change

    // Increase count for next order (starting count at 2 as this hook is triggered after shipping items hook)
    set_option('wc_orders_count_for_shipping', $orders_count > 0 ? $orders_count + 1 : 2 ); 
}

// Set shipping cost to zero every 10-th orders when order is placed
add_action( 'woocommerce_checkout_create_order_shipping_item', 'action_wc_checkout_create_order_shipping_item', 10, 4 );
function action_wc_checkout_create_order_shipping_item( $item, $package_key, $package, $order ) {
    $orders_count = (int) get_option('wc_orders_count_for_shipping');

    // Every 10-th orders 
    if( $orders_count > 0 && ( $orders_count % 10 ) === 0 ) {
        $item->set_total( '0' );
        $item->set_taxes( [ 'total' => '0' ] );
        $item->set_total_tax( '0' );
    }   
} 

Code goes in functions.php file of your active child theme (or active theme). It should works.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
0

A simple way of changing the shipping price is this:

add_filter( 'woocommerce_package_rates', 'woocommerce_package_rates' );
function woocommerce_package_rates( $rates ) {
    foreach($rates as $key => $rate ) {
        $rates[$key]->cost = 10;
    }
    return $rates;
}

Add conditional statement if applicable by quantity or total price

add_filter( 'woocommerce_package_rates', 'woocommerce_package_rates', 10, 2 );
function woocommerce_package_rates( $rates, $package ) {
    $new_cost = ( WC()->cart->subtotal < 10 ) ? 4.5 : 2.5;
    foreach($rates as $key => $rate ) {
        $rates[$key]->cost = $new_cost;
    }
    return $rates;
}
Always Helping
  • 14,316
  • 4
  • 13
  • 29
  • It is not the intention to copy / paste already existing answers as an answer, instead refer to the existing answer. https://stackoverflow.com/questions/43881390/woocommerce-change-the-shipping-cost-related-with-the-subtotal & https://reigelgallarde.me/programming/woocommerce-shipping-fee-changes-condition-met/ – 7uc1f3r Jun 09 '20 at 08:53
  • Thanks, but I need to change shipping price in every n-th order. In my example code, I will add something like this: `if ($order_id % 10 == 0) { // change shipping price for every 10-th order }` That's why I noticed in my question "after order creation". Is it possible in your example? Maybe I missing something... – Alex Skutin Jun 09 '20 at 08:56
  • @7uc1f3r its was never the intentions to copy paste nor i had. In addition, i do not know if there is an existing answer as you highlighted. I have used the same code on one of my projects. Thanks Anyway. As long as its helps the person asking question. – Always Helping Jun 10 '20 at 00:50