0

I have some old orders which are still processing and want to change their shipping method to the new one which I'm using now. Some processing orders uses another shipping method so in this case I should check not only the order status but shipping method ID as well. I try to do this but unfortunatelly no luck.

Based on @LoicTheAztec answer code there, this is my attempt:

function change_shipping($order, $calculate_tax_for, $shipping_methods ) {
    // Here set your shipping method ID replacement
    $old_method_id ='multiparcels_lp_express_courier';
    $new_method_id ='dpd_home_delivery';
    
    // Get the the WC_Order Object from an order ID (optional)
    $order = wc_get_order( $order_id );
    
    // Array for tax calculations
    $calculate_tax_for = array(
        'country'  => $order->get_shipping_country(),
        'state'    => $order->get_shipping_state(), // (optional value)
        'postcode' => $order->get_shipping_postcode(), // (optional value)
        'city'     => $order->get_shipping_city(), // (optional value)
    );
    
    if ($order->data['status'] == 'processing' && $shipping_method->id == $old_method_id ) {
    
    $changed = false; // Initializing
    
    // Loop through order shipping items
    foreach( $order->get_items( 'shipping' ) as $item_id => $item ){
    
        // Retrieve the customer shipping zone
        $shipping_zone = WC_Shipping_Zones::get_zone_by( 'instance_id', $item->get_instance_id() );
    
        // Get an array of available shipping methods for the current shipping zone
        $shipping_methods = $shipping_zone->get_shipping_methods();
    
        // Loop through available shipping methods
        foreach ( $shipping_methods as $instance_id => $shipping_method ) {
    
            // Targeting specific shipping method
            if( $shipping_method->is_enabled() && $shipping_method->id === $new_method_id ) {
    
                // Set an existing shipping method for customer zone
                $item->set_method_title( $shipping_method->get_title() );
                $item->set_method_id( $shipping_method->get_rate_id() ); // set an existing Shipping method rate ID
                $item->set_total( $shipping_method->cost );
    
                $item->calculate_taxes( $calculate_tax_for );
                $item->save();
    
                $changed = true;
                break; // stop the loop
            }
        }
    }
    
    if ( $changed ) {
        // Calculate totals and save
        $order->calculate_totals(); // the save() method is included
    }
    
    }
    
    }
    add_action ('change_shipping', true);
lituoklis13
  • 77
  • 1
  • 1
  • 6
  • @7uc1f3r thanks for your answer. I edit my message and mentioned which was this code author and add link to that thread – lituoklis13 Apr 05 '22 at 12:14
  • 1
    your code won't run, simply because the `change_shipping` action hook doesn't exist, in short... your function won't be called and run. It is also written for 1 specific order(ID) while I believe you want to update multiple orders – 7uc1f3r Apr 05 '22 at 12:15
  • @7uc1f3r Yes, you are correct. I want to update multiple orders. Which hook should I use and how to change the code to use multiple ID's, not only one? – lituoklis13 Apr 05 '22 at 13:24
  • @lituoklis13 How many orders need to be updated? Does this function only need to be performed once for old orders? Solutions may vary based on the number of orders to be updated and whether this functionality should also apply to future orders. – Vincenzo Di Gaetano Apr 05 '22 at 20:46
  • @VincenzoDiGaetano There is around 150 orders which should be updated and has that two conditions (status is processing and has specific shipping method id). I only need to run this function once and no need it for the future. – lituoklis13 Apr 05 '22 at 22:20
  • @7uc1f3r I guess the best solution is to execute that functon as cron job, right? So only need help with how to change that code that all orders would be selected – lituoklis13 Apr 06 '22 at 19:22

0 Answers0