Ad

Split Shipping(Multi Shipping) - Get Array According To Product Id, Product Shipping Class And Shipping Method From Order Id

- 1 answer

I have implement split shipping according to cart product shipping_class_id. and its working fine see screenshot and code:

add_filter('woocommerce_cart_shipping_packages', 'woo_cart_shipping_packages');

    function woo_cart_shipping_packages($packages)
    {
        foreach (WC()->cart->get_cart() as $item) 
        {
            if ($item['data']->needs_shipping()) 
            {
                $get_shipping_class = $item['data']->get_shipping_class();
                $shipping_classes[] = $get_shipping_class;

                $regular_items[$get_shipping_class][] = $item;
                $check_chrono_shipping = false;
            }
        }

        if ($regular_items) 
        {
            $i = 1;
            $shipping_methods = WC()->shipping->get_shipping_methods();

            foreach ($shipping_methods as $shipping_method) 
            {
                if (!in_array($shipping_method->id, $chrono_shipping_method_ids)) 
                {
                    $shipping_method_ids[] = $shipping_method->id;
                }
            }
            if(!$chrono_multi_shipping && !$fresh_dry_products && !$check_chrono_shipping){
                $shipping_method_ids = array_merge($shipping_method_ids, $chrono_not_fresh_not_freeze);
            }

            foreach ($regular_items as $ship_via => $new_package) {

                $shipping_class_name = 'Regular Shipping ' . $i;
                $get_shipping_class_name = get_term_by('slug', $ship_via, 'product_shipping_class');

                if ($get_shipping_class_name) 
                {
                    $shipping_class_name = ucwords($get_shipping_class_name->name);
                }

                $packages[] = array(
                    'ship_via' => $shipping_method_ids ?: array('flat_rate', 'local_pickup', 'free_shipping'),
                    'name' => $shipping_class_name,
                    'contents' => $new_package,
                    'contents_cost' => array_sum(wp_list_pluck($new_package, 'line_total')),
                    'applied_coupons' => WC()->cart->applied_coupons,
                    'destination' => array(
                        'country' => WC()->customer->get_shipping_country(),
                        'state' => WC()->customer->get_shipping_state(),
                        'postcode' => WC()->customer->get_shipping_postcode(),
                        'city' => WC()->customer->get_shipping_city(),
                        'address' => WC()->customer->get_shipping_address(),
                        'address_2' => WC()->customer->get_shipping_address_2()
                    )
                );
                $i++;
            }
        }
        return $packages;
    }

I am facing issue on thankyou.php: After place order we need to find product_id, shipping_class, shipping method in a array according to order id.

Problem:

   //$order = wc_get_order($order_id);
   $order_shippings = array();

   foreach ($order->get_items() as $item_key => $item ){
        $product_id = $item->get_product_id();
        $shipping_class_id     = $product->get_shipping_class_id();
        $shipping_class_term   = get_term($shipping_class_id, 'product_shipping_class');
        $product_shipping_slug = $shipping_class_term->slug ?: '';

        $order_shippings[$product_id] = $shipping_class_id;
        $order_shippings[$product_id] = $product_shipping_slug;
   }

In this way, we got product id, and shipping class But unable to got which shipping method apply for this product?

Problem 2:

foreach ($order->get_items('shipping') as $item_id => $shipping_item_obj){
        $shipping_method_id = $shipping_item_obj->get_method_id();
        $order_shippings['shipping_method_name']     = $shipping_item_obj->get_name();
        $order_shippings['shipping_method_title']    = $shipping_item_obj->get_method_title();
}

In this way, we got shipping_method_id but unable to got which product applied this shipping method.

Need Solution: Actually i want to get separately product id, applied shipping class, applied shipping method from any/given order_id.

enter image description here

Ad

Answer

As I am checking your code it's fine you should follow few steps like

store your shipping methods which you want to split order accordenly

$woo_freeze_shipping = array('shipping_methods');
$woo_fresh_product =  array('shipping_methods')
$woo_not_fresh_not_freeze = array('shipping_methods');

Then use $order->get_items('shipping') like this:

            $records = $order_shippings = $shipping_classess = array();
            foreach ($order->get_items('shipping') as $item_id => $shipping_item_obj) 
            {
                $shipping_method_id = $shipping_item_obj->get_method_id();
                $order_shippings[$shipping_method_id]['shipping_method_name']        = $shipping_item_obj->get_name();
                $order_shippings[$shipping_method_id]['shipping_method_title']       = $shipping_item_obj->get_method_title();
                $order_shippings[$shipping_method_id]['shipping_method_instance_id'] = $shipping_item_obj->get_instance_id(); // The instance ID
                $order_shippings[$shipping_method_id]['shipping_method_total']       = $shipping_item_obj->get_total();
                $order_shippings[$shipping_method_id]['shipping_method_total_tax']   = $shipping_item_obj->get_total_tax();
                $order_shippings[$shipping_method_id]['shipping_method_taxes']       = $shipping_item_obj->get_taxes();
                
                if (in_array($shipping_method_id, $woo_freeze_shipping)) 
                {
                    $order_shippings['freeze-product'] = $shipping_method_id;
                } 
                elseif (in_array($shipping_method_id, $woo_fresh_product)) 
                {
                    $order_shippings['fresh-product'] = $shipping_method_id;
                } 
                elseif (in_array($shipping_method_id, $woo_not_fresh_not_freeze)) 
                {
                    $order_shippings['not-fresh-not-freeze'] = $shipping_method_id;
                } 
                else
                {
                    $order_shippings['regular_shipping'] = $shipping_method_id;
                }
            }

In this way, you can store shipping method info in $order_shippings according to your split shipping class(freeze-product,freeze-product,not-fresh-not-freeze)

Now by using foreach ($order->get_items() as $item_id => $item) you can manage and create new order seprately

Full example:

add_action('woocommerce_thankyou', 'woo_split_order_items', 10, 1);

if (!function_exists('woo_split_order_items'))
{
    function woo_split_order_items($order_id)
    {
        global $order_ids, $woo_freeze_shipping, $woo_fresh_product, $woo_not_fresh_not_freeze;
    
        if (!$order_id) {
           return;
        }

        $order = wc_get_order($order_id);

        if (!get_post_meta($order_id, '_thankyou_action_done', true) && ( is_checkout() || is_wc_endpoint_url('order-received') ))
        {
            $records = $order_shippings = $shipping_classess = array();
            $variable = false;

            foreach ($order->get_items('shipping') as $item_id => $shipping_item_obj) 
            {
                $shipping_method_id = $shipping_item_obj->get_method_id();
                $order_shippings[$shipping_method_id]['shipping_method_name']        = $shipping_item_obj->get_name();
                $order_shippings[$shipping_method_id]['shipping_method_title']       = $shipping_item_obj->get_method_title();
                $order_shippings[$shipping_method_id]['shipping_method_instance_id'] = $shipping_item_obj->get_instance_id(); // The instance ID
                $order_shippings[$shipping_method_id]['shipping_method_total']       = $shipping_item_obj->get_total();
                $order_shippings[$shipping_method_id]['shipping_method_total_tax']   = $shipping_item_obj->get_total_tax();
                $order_shippings[$shipping_method_id]['shipping_method_taxes']       = $shipping_item_obj->get_taxes();
                
                if (in_array($shipping_method_id, $woo_freeze_shipping)) 
                {
                    $order_shippings['freeze-product'] = $shipping_method_id;
                } 
                elseif (in_array($shipping_method_id, $woo_fresh_product)) 
                {
                    $order_shippings['fresh-product'] = $shipping_method_id;
                } 
                elseif (in_array($shipping_method_id, $woo_not_fresh_not_freeze)) 
                {
                    $order_shippings['not-fresh-not-freeze'] = $shipping_method_id;
                } 
                else
                {
                    $order_shippings['regular_shipping'] = $shipping_method_id;
                }
            }
            
            $records['order'] = array(
                'order_id'             => $order->get_id(),
                'currency'             => $order->get_currency(),
                'payment_method'       => $order->get_payment_method(),
                'payment_method_title' => $order->get_payment_method_title(),
                'status'               => $order->get_status() ?: 'pending',

                'shipping_address'     => $order->get_address('shipping'),
                'billing_address'      => $order->get_address('billing'),

                'customer_id'         => $order->get_customer_id(),
                'user_id'             => $order->get_user_id(),
                'customer_ip_address' => $order->get_customer_ip_address(),
                'customer_user_agent' => $order->get_customer_user_agent(),
                'created_via'         => $order->get_created_via(),
                'customer_note'       => $order->get_customer_note(),
            );

            foreach ($order->get_items() as $item_id => $item) 
            {
                if (isset($item['product_id']) && $item['product_id']>0) 
                {
                    $product               = $item->get_product();
                    $shipping_class_id     = $product->get_shipping_class_id();
                    $shipping_class_term   = get_term($shipping_class_id, 'product_shipping_class');
                    $product_shipping_slug = $shipping_class_term->slug;

                    if ($product->is_type('variation')) 
                    {
                        $parent_id     = $product->get_parent_id();
                        $variation_id  = $product->get_id();
                        $variable_prod = $product;
                        $product       = wc_get_product($product->get_parent_id());
                        $variable      = true;
                    }
                    else{
                        $parent_id     = $item['parent_id'] ?: 0;
                        $variation_id  = $item->get_variation_id() ?: 0;
                        $variable_prod = null;
                        $variable      = false;
                    }

                    if ($order_shippings[$product_shipping_slug]) 
                    {
                        $product_shipping_class = $product_shipping_slug;   
                    } 
                    else if($product_shipping_slug == 'not-fresh-not-freeze')
                    {
                        $product_shipping_class = 'fresh-product';
                    }
                    else 
                    {
                        $product_shipping_class = 'regular_shipping';
                    }
                    $shipping_classess[]         = $product_shipping_class;

                    $shipping_method             = $order_shippings[$product_shipping_class] ?: '';
                    $shipping_method_name        = $order_shippings[$shipping_method]['shipping_method_name'] ?: '';
                    $shipping_method_title       = $order_shippings[$shipping_method]['shipping_method_title'] ?: '';
                    $shipping_method_instance_id = $order_shippings[$shipping_method]['shipping_method_instance_id'] ?: '';
                    $shipping_method_total       = $order_shippings[$shipping_method]['shipping_method_total'] ?: 0;
                    $shipping_method_total_tax   = $order_shippings[$shipping_method]['shipping_method_total_tax'] ?: 0;
                    $shipping_method_taxes       = $order_shippings[$shipping_method]['shipping_method_taxes'] ?: array('total' => array());

                    $product_shippings = array(
                        'product_id'                  => $item_id,
                        'product_shipping_class'      => $product_shipping_class,
                        'shipping_class_id'           => $shipping_class_id,
                        'shipping_method'             => $shipping_method,
                        'shipping_method_name'        => $shipping_method_name,
                        'shipping_method_title'       => $shipping_method_title,
                        'shipping_method_instance_id' => $shipping_method_instance_id,
                        'shipping_method_total'       => $shipping_method_total,
                        'shipping_method_total_tax'   => $shipping_method_total_tax,
                        'shipping_method_taxes'       => $shipping_method_taxes,
                    );

                    $ordered_products = array(
                        'product_id'        => $item_id,
                        'parent_id'         => $parent_id,
                        'variation_id'      => $variation_id,
                        'name'              => $item->get_name(),
                        'quantity'          => $item->get_quantity(),
                        'subtotal'          => $item->get_subtotal(),
                        'tax'               => $item->get_subtotal_tax(),
                        'total'             => $item->get_total(),
                        'taxclass'          => $item->get_tax_class(),
                        'taxstat'           => $item->get_tax_status(),
                        'allmeta'           => $item->get_meta_data(),
                        'somemeta'          => $item->get_meta('_whatever', true),
                        'type'              => $item->get_type(),
                        'taxes'             => $item->get_taxes(),
                        'line_subtotal'     => $item->get_subtotal(), // Line subtotal (non discounted)
                        'line_subtotal_tax' => $item->get_subtotal_tax(), // Line subtotal tax (non discounted)
                        'line_total'        => $item->get_total(), // Line total (discounted)
                        'line_total_tax'    => $item->get_total_tax(), // Line total tax (discounted)
                        'variable' => $variable,
                        'variable_prod' => $variable_prod,
                        'product' => $product,
                    );

                    $records['product'][$product_shipping_class]['shipping'] = $product_shippings;
                    $records['product'][$product_shipping_class]['items'][] = $ordered_products;    
                }
            }

            $shipping_classess = array_filter(array_unique($shipping_classess));
            
            if((isset($records['product']) && !empty($records['product'])) && (isset($shipping_classess) && count($shipping_classess)>1) )
            {   
                $ordered_product = $order_ids = array();

                foreach ($records['product'] as $product_shipping_class => $items)
                {
                    $order_status = $records['order']['status'];

                    /*==== SET SHIPPING IN A ORDER ====== */
                    $shipping_title = $items['shipping']['shipping_method_title'];
                    $shipping_method_name = $items['shipping']['shipping_method_name'];
                    $shipping_method_id = $items['shipping']['shipping_method'];

                    /*=====UPDATE Extra Shipping Label =======*/
                    // if(empty($ordered_product)){
                    //  // Remove all items - we will re-add them later.
                    //  $order->remove_order_items();
                    // }else{
                    //  $order = new WC_Order($args);
                    // }

                    /*==== NEW ORDER ARGS ====== */
                    $args = array(
                        'order_id' => null,
                        'status' => $order_status
                    );

                    /*===== CREATE NEW ORDER FROM ORIGNAL ORDER ============*/
                    $new_order = new WC_Order($args);

                    foreach ($items['items'] as $product) 
                    {
                        if (isset($product['variation_id']) && absint($product['variation_id'])>0) 
                        {
                            $product_id = absint($product['parent_id']);
                        } 
                        else 
                        {
                            $product_id = absint($product['product_id']);
                        }

                        if ($product_id>0 && !in_array($product_id, $ordered_product)) 
                        {
                            $new_product  = $product['product'] ?: null;
                            $variable_prod= $product['variable_prod'] ?: null;
                            $variation_id = absint($product['variation_id']) ?: 0;
                            $quantity     = absint($product['quantity']) ?: 1;
                            $variable     = $product['variable'] ?: false;
                            $subtotal     = $product['subtotal'] ?: 0;
                            $total        = $product['total'] ?: 0;
                            $subtotal_tax = $product['tax'] ?: 0;
                            $total_tax    = $product['line_total_tax'] ?: 0;
                            $taxes        = $product['taxes'];
                            
                            /*==== SET LINE TOTAL ====== */
                            $new_item = new WC_Order_Item_Product();
                            $new_item->set_backorder_meta();
                            $new_item->set_product($new_product);

                            $new_item->set_props([
                                'quantity' => $quantity,
                                'subtotal' => $subtotal,
                                'total' => $total,
                                'subtotal_tax' => $subtotal_tax,
                                'total_tax' => $total_tax,
                                'taxes' => $taxes,
                            ]);

                            $new_order->add_item($new_item);

                            array_push($ordered_product, $product_id);
                        } 
                    } //# End multi product loop

                    $shipping_method = new WC_Order_Item_Shipping();
                    $shipping_rate = new WC_Shipping_Rate();
                    $shipping_rate->set_method_id($shipping_method_id);
                    $shipping_rate->set_instance_id($items['shipping']['shipping_method_instance_id']);
                    $shipping_rate->set_label($shipping_title);
                    $shipping_rate->set_cost($items['shipping']['shipping_method_total']);

                    $shipping_method->set_name($shipping_method_name);
                    $shipping_method->set_method_title($shipping_title);
                    $shipping_method->set_method_id($shipping_method_id);
                    $shipping_method->set_instance_id($items['shipping']['shipping_method_instance_id']);
                    $shipping_method->set_total($items['shipping']['shipping_method_total']);

                    $shipping_method->set_shipping_rate($shipping_rate);
                    $new_order->add_item($shipping_method);

                    /*==== SET ORDER META ====== */
                    $new_order->set_currency($records['order']['currency'] ?: get_woocommerce_currency());
                    $new_order->set_customer_id($records['order']['customer_id'] ?: get_current_user_id());
                    $new_order->set_created_via($records['order']['created_via'] ?: 'checkout');
                    $new_order->set_customer_ip_address($records['order']['customer_ip_address'] ?: $_SERVER['REMOTE_ADDR']);
                    $new_order->set_customer_user_agent($records['order']['customer_user_agent'] ?: '');
                    $new_order->set_customer_note(isset($records['order']['customer_note']) ? $records['order']['customer_note'] : '');

                    /*==== SET PAYMENT GATWAY ORDER ====== */
                    if (isset($records['order']['payment_method']) && $records['order']['payment_method']) 
                    {
                        $new_order->set_payment_method($records['order']['payment_method']);
                    }

                    /*==== SET COUPONS ORDER ====== */
                    if (WC()->cart && $coupons = WC()->cart->get_coupons()) 
                    {
                        foreach ($coupons as $code => $coupon) 
                        {
                            $coupon_item = new WC_Order_Item_Coupon(
                                array(
                                    'code' => $code, 
                                    'discount' => WC()->cart->get_coupon_discount_amount($code), 
                                    'discount_tax' => WC()->cart->get_coupon_discount_tax_amount($code)
                                )
                            );
                            $new_order->add_item($coupon_item);
                        }
                    }

                    /*==== SET ADDRESS ORDER ====== */
                    if (isset($records['order']['billing_address'])) 
                    {
                        $new_order->set_address($records['order']['billing_address'], 'billing');
                    }

                    if (isset($records['order']['shipping_address'])) 
                    {
                        $new_order->set_address($records['order']['shipping_address'], 'shipping');
                    }

                    /*==== CALCULATE TOTALS ====== */
                    $new_order->calculate_totals();
                    $new_order->update_status($order_status, '<p>Order created dynamically from chronofood</p>', TRUE);

                    /*==== SAVE ORDER ====== */
                    $new_order->update_meta_data('_thankyou_action_done', true);

                    if($new_order->save()){

                        array_push($order_ids, $new_order->id);
                        
                    }

                } // # End Create new order loop

                /* Change existing /orignal order status */
                $order->update_status('split-status', '<p>Orignal Order splited</p>', TRUE);

                /* Flag the action as done (to avoid repetitions on reload for example) */
                add_post_meta($order_id, '_thankyou_action_done', true, true);
                $order->update_meta_data('_thankyou_action_done', true);
            }
        }
    }
}
Ad
source: stackoverflow.com
Ad