WooCommerce – Split Multiple Items into Individual Line Items
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' );
}
Leave an answer