0

I'm looking to split line items with a quantity > 1, into individual line items AFTER the order is received. I'm read a lot about this and see a bunch of great scripts that do this before the checkout process occurs such as https://businessbloomer.com/woocommerce-display-separate-cart-items-product-quantity-1/ and https://stackoverflow.com/questions/32485152/woocommerce-treat-cart-items-separate-if-quantity-is-more-than-1?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa.

Does anyone have any thoughts about how to do this AFTER the order has been completed? Or right on order creation in WooCommerce? I want anything with quantity > 1 to be broken out into individual line items.

So I believe I'll need to access all line items and then find those with quantity > 1 and then add new line items and decrement the quantity until it all balances out. Where I could use some help is how to create a line item? I know I can inspect them as shown below:

function inspect_line_items() 
{
  $order = wc_get_order( 390 );
    foreach ($order->get_items() as $item_id => $item_data) {

    // Get an instance of corresponding the WC_Product object
    $product = $item_data->get_product();
    $product_name = $product->get_name(); // Get the product name

    $item_quantity = $item_data->get_quantity(); // Get the item quantity

    $item_total = $item_data->get_total(); // Get the item line total

    // Displaying this data (to check)
    if ($item_quantity >1 ){
        echo 'HALP!';

      }
    }
}

Ok I'm continuing to try and I've been able to add line items (this isn't prod just testing it out, obviously this has some gaps :) ). That being said I can add a new item after checkout, and then with another hook change the order status back to processing. The issue is now the prices that are displayed. Even if I decrement the quantity for a particular item, it will still show the full/original cost. I tried updating the sub_total and total fields and then I get this funky Discount: line item. Any thoughts? Am I one the right track here?

add_action( 'woocommerce_checkout_create_order', 'change_total_on_checking', 20, 1 );
function change_total_on_checking( $order ) {
    // Get order total
    $total = $order->get_total();
    $items = $order->get_items();
    foreach ($order->get_items() as $item_id => $item_data) {

    // Get an instance of corresponding the WC_Product object
        $product = $item_data->get_product();
        $product_id = $item_data->get_id();
        $product_name = $product->get_name();
        $price = $product->get_price();


        $item_quantity = $item_data->get_quantity();
        $item_data['quantity'] = $item_data['quantity'] - 1 ; // Get the item quantity
        //$item_data['total'] = $item_data['total'] - $price;
        //$item_data['sub_total'] = $item_data['sub_total'] - $price;

        $item_total = $item_data->get_total(); // Get the item line total


        //do_action('woocommerce_add_to_order', $item_data['id'], $item_data['product_id'], $item_quantity, $item_data['variation_id']);
        WC()->cart->add_to_cart( $product_id, $item_quantity );
        $order->add_product( $product, 1);
        $order->calculate_totals(); // updating totals

        $order->save(); // Save the order data


    }

}

add_action( 'woocommerce_thankyou', 'woocommerce_thankyou_change_order_status', 10, 1 );
function woocommerce_thankyou_change_order_status( $order_id ){
    if( ! $order_id ) return;

    $order = wc_get_order( $order_id );

    $order->update_status( 'processing' );
}
1

So I ended up combining a few answer out there and split out orders when adding to the cart, and also when updating the cart. The below works, though it's purely a front end customization. Hope this helps someone else!

function bbloomer_split_product_individual_cart_items( $cart_item_data, $product_id ){
  $unique_cart_item_key = uniqid();
  $cart_item_data['unique_key'] = $unique_cart_item_key;
  return $cart_item_data;
}

add_filter( 'woocommerce_add_cart_item_data', 'bbloomer_split_product_individual_cart_items', 10, 2 );  

add_action( 'woocommerce_after_cart_item_quantity_update', 'limit_cart_item_quantity', 20, 4 );
function limit_cart_item_quantity( $cart_item_key, $quantity, $old_quantity, $cart ){

    // Here the quantity limit
    $limit = 1;
    $orders_added = $quantity - $limit;

    if( $quantity > $limit ){
        //Set existing line item quantity to the limit of 1
        $cart->cart_contents[ $cart_item_key ]['quantity'] = $limit;
        //get product id of item that was updated
        $product_id = $cart->cart_contents[ $cart_item_key ][ 'product_id' ];

        for( $i = 0; $i< $orders_added; $i++ ){
            //iterate over the number of orders you must as with quantity one
            $unique_cart_item_key = uniqid();
            //create unique cart item ID, this is what breaks it out as a separate line item
            $cart_item_data = array();
            //initialize cart_item_data array where the unique_cart_item_key will be stored
            $cart_item_data['unique_key'] = $unique_cart_item_key;
            //set the cart_item_data at unique_key = to the newly created unique_key

            //add that shit! this does not take into account variable products

            $cart->add_to_cart( $product_id, 1, 0, 0, $cart_item_data );

        }

        // Add a custom notice
        wc_add_notice( __('We Split out quantities of more than one into invididual line items for tracking purposes, please update quantities as needed'), 'notice' );
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.