skip to Main Content

I’m writing a code for Woocommerce that will automatically combine all the orders that come in from the same customer until we flip the status. The only problem I’m having is that line items are being duplicated when a customer places a second order containing one of the same items as on a previous order. This makes picking orders more confusing for our staff.

I have included a section that checks to see if the item exists in the previous order, and it then updates the quantity of that item instead of adding a new line. This part of the code is causing an error at checkout: "Error processing checkout. Please try later." Without this part of the code, everything works as expected.

// Add a custom function to check and combine orders
function combine_orders_on_status_change($order_id) {
    // Get the current order
    $current_order = wc_get_order($order_id);

    // Check if the order status is 'on-hold'
    if ($current_order->get_status() === 'on-hold') {
        // Get user ID of the current order
        $user_id = $current_order->get_user_id();

        // Get all orders of the same user with status 'on-hold'
        $args = array(
            'post_type'      => 'shop_order',
            'post_status'    => 'wc-on-hold',
            'posts_per_page' => -1,
            'meta_query'     => array(
                array(
                    'key'   => '_customer_user',
                    'value' => $user_id,
                ),
            ),
        );

        $orders = get_posts($args);

        // Find the older order with added items to combine with
        $older_order = null;
        foreach ($orders as $order_post) {
            $order_to_combine = wc_get_order($order_post->ID);

            // Check if it's not the same order and it's not already combined
            if ($order_to_combine && $order_to_combine->get_id() !== $order_id && $order_to_combine->get_status() !== 'combined') {
                // Check if shipping addresses match (if present in both orders)
                $current_shipping_address = $current_order->get_address('shipping');
                $combine_shipping_address = $order_to_combine->get_address('shipping');
                if (!empty($current_shipping_address) && !empty($combine_shipping_address) && $current_shipping_address !== $combine_shipping_address) {
                    continue; // Skip combining if shipping addresses don't match
                }

                // Check if delivery dates match (if present in both orders)
                $current_delivery_date = $current_order->get_meta('_orddd_timestamp', true);
                $combine_delivery_date = $order_to_combine->get_meta('_orddd_timestamp', true);
                if (!empty($current_delivery_date) && !empty($combine_delivery_date) && $current_delivery_date !== $combine_delivery_date) {
                    continue; // Skip combining if delivery dates don't match
                }

                // Set the older order with added items to combine with
                $older_order = $order_to_combine;
                break; // Stop after finding the first eligible order
            }
        }

        // If an older order with added items was found, combine orders
        if ($older_order) {
            // Check if the older order is transitioning from 'received' to 'processing'
            if ($older_order->get_status() === 'on-hold' && $current_order->get_status() === 'processing') {
                return;
            }

            // Combine orders by copying items
            $combined_items_list = array();
            foreach ($current_order->get_items() as $item) {
                $product_id = $item->get_product_id();
                $quantity = $item->get_quantity();

                // Check if the product already exists in the combined order
                $existing_item = $older_order->get_item($product_id);

                if ($existing_item) {
                    // If the product exists, update the quantity
                    $existing_quantity = $existing_item->get_quantity();
                    $older_order->set_quantity($existing_item, $existing_quantity + $quantity);
                } else {
                    // If the product does not exist, add it to the combined order
                    $older_order->add_product(wc_get_product($product_id), $quantity);
                }
                
                $combined_items_list[] = $item->get_name() . ' x' . $quantity;
                
                // Restore stock for each item
                wc_update_product_stock($product_id, $quantity, 'increase');
            }
            
            // Copy customer notes with clear delineation
            $custom_order_number = $current_order->get_order_number();
            $customer_note = $current_order->get_customer_note();
            if (!empty($customer_note)) {
                $existing_notes = $older_order->get_customer_note();
                $combined_notes = $existing_notes . "n--- Note from Order #" . $custom_order_number . " ---n" . $customer_note;
                $older_order->set_customer_note($combined_notes);
            }

            // Move the current order with added items to 'combined' status
            $current_order->update_status('combined', __('Orders combined', 'astra'));

            // Add a note to the order log
            $combined_items_log = implode(', ', $combined_items_list);
            $note_combined = sprintf(__('Order combined with Order #%s. Items added: %s', 'astra'), $custom_order_number, $combined_items_log);
            $older_order->add_order_note($note_combined);

            // Log entry for the newer order
            $note_newer = sprintf(__('Items added to Order #%s during combination.', 'astra'), $older_order->get_order_number());
            $current_order->add_order_note($note_newer);
            
            $older_order->calculate_totals();

            // Save changes to the orders
            $older_order->save();
            $current_order->save();
            
            // Fire the update order action hook after the old_order is saved
            wc_reduce_stock_levels($older_order->get_id());
        }
    }
}

// Hook into order status change
add_action('woocommerce_order_status_changed', 'combine_orders_on_status_change', 10, 3);

2

Answers


  1. The information you probided is not enough but try these i hope it works:

    Finding items:

    $existing_item = null;
    foreach ($older_order->get_items() as $item_id => $item_data) {
        if ($item_data->get_product_id() == $product_id) {
            $existing_item = $item_data;
            break;
        }
    }
    

    Updating quantity:

    $existing_item->set_quantity($existing_quantity + $quantity);
    $existing_item->save();
    

    Error handling and debug:
    Enable WP_DEBUG by adding this code to wp-config.php

    ini_set( 'log_errors', 'On' );
    ini_set( 'display_errors', 'On' );
    ini_set( 'error_reporting', E_ALL );
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG', true );
    define( 'WP_DEBUG_DISPLAY', true );
    

    Also add error handling to catch any issues that occur during the order combination process. This will help identify the specific part of the process that is causing the error.

    Login or Signup to reply.
  2. It looks like your code is designed to combine orders for the same customer with the status ‘on-hold’ and then update the status to ‘combined’. The issue you’re facing is related to the logic that checks for existing items in the older order and updates their quantities.

    To address the error at checkout, you may need to make some adjustments to how you handle item quantities. Below are some suggestions:

    1. Check if the Product Exists with the Correct Quantity:
      Before updating the quantity of an existing item, check if the product exists in the older order with the correct quantity. If it does, there’s no need to update the quantity.

      $existing_item = $older_order->get_item($product_id);
      
      if ($existing_item) {
          // Check if the product exists with the correct quantity
          $existing_quantity = $existing_item->get_quantity();
      
          if ($existing_quantity !== $quantity) {
              // Update the quantity
              $older_order->set_quantity($existing_item, $existing_quantity + $quantity);
          }
      } else {
          // If the product does not exist, add it to the combined order
          $older_order->add_product(wc_get_product($product_id), $quantity);
      }
      
    2. Use set_quantity Correctly:
      Ensure that you are using set_quantity correctly. The method set_quantity expects the second argument to be the new quantity, not the quantity to add. If you want to increase the quantity, you should do so explicitly.

      $existing_quantity = $existing_item->get_quantity();
      $older_order->set_quantity($existing_item, $existing_quantity + $quantity);
      
    3. Ensure Stock Availability:
      Double-check that your stock management is correctly handled, especially when updating quantities. If you’re updating quantities, make sure to handle stock adjustments accordingly.

      // Restore stock for each item
      wc_update_product_stock($product_id, $quantity, 'increase');
      

      Ensure that this line is appropriate for your use case and that it doesn’t conflict with other stock-related actions.

    By making these adjustments, you can ensure that the quantities are handled correctly, and it might resolve the error at checkout. Additionally, consider checking the WooCommerce logs for more detailed error messages that could provide insights into the specific issue during checkout.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search