New Order Check Implementation

User
At the moment, we manually search a customers billing/shipping name and postcode (if different) across the whole orders database for every order we receive.
This allows us to check their order history so we can action the order accordingly.
As you can imagine, this is very time-consuming and adds burden on the system and is unneccessary for new customers that ends up not having any other order history.
To reduce the workload, we would like to automate some of this process.
Therefore we were hoping for every order that is placed, if the system can automatically check to make sure there are no other orders with the customer/shipping name, customer/shipping address and postcode, account or email.
Please note: the reason we would have to check all these fields and not just if it is a new account is because sometimes a user may create a new account, but have an order history under different accounts so it is still important to flag customers with the same shipping/billing name, email, shipping/billing address/postcode etc. so we can view their full order history.
If there are no other orders present, then it would be good if on the orders dashboard this order can be denoted with a green dot or something similar to signify that it is a new customer.
Therefore if an order comes in with a green dot annotation, then we know we do not need to check the order history as it is a new customer.
Ideally, this green dot or annotation should be a 'screen option' so it can be enabled/disabled on the order dashboard as we chose (if this is simple enough).
Importantly, in regards to this task we wanted to discuss and make sure if the system automatically runs these checks it would not add increased burden on the system and cause issues/slowdown etc.
create above functionality in wordpress using wp shedule tasks
Assistant
To implement this functionality efficiently in WordPress using WooCommerce and WP Cron (scheduled tasks), we can follow these steps:

### **Approach**
1. **Scheduled Task Execution**
– Use `wp_schedule_event()` to run a background task that checks new orders for duplicate customer details.
– The task will compare the new order’s billing/shipping name, address, postcode, email, and account with existing orders in the WooCommerce database.

2. **Order Flagging**
– If no matching orders are found, add a custom meta field to the order (`_is_new_customer`) and set it to `yes`.
– If a match is found, set `_is_new_customer` to `no`.

3. **Order Dashboard Customization**
– Modify the WooCommerce Orders list to display a green dot for orders with `_is_new_customer = yes`.
– Add a screen option to enable/disable this functionality dynamically.

### **Implementation**
Here’s the full implementation in your child theme’s `functions.php` or a custom plugin:

#### **1. Schedule the Task**

function schedule_customer_check() {
    if (!wp_next_scheduled('check_new_customer_orders')) {
        wp_schedule_event(time(), 'hourly', 'check_new_customer_orders');
    }
}
add_action('wp', 'schedule_customer_check');

#### **2. Background Task to Check Order History**

function check_new_customer_orders() {
    $args = array(
        'status' => 'processing', // Modify if needed
        'limit'  => -1,
        'meta_query' => array(
            array(
                'key'     => '_is_new_customer',
                'compare' => 'NOT EXISTS',
            ),
        ),
    );

    $orders = wc_get_orders($args);

    foreach ($orders as $order) {
        $billing_name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
        $shipping_name = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
        $billing_address = $order->get_billing_address_1();
        $shipping_address = $order->get_shipping_address_1();
        $postcode = $order->get_billing_postcode();
        $email = $order->get_billing_email();
        $customer_id = $order->get_customer_id();

        global $wpdb;
        $existing_orders = $wpdb->get_var($wpdb->prepare("
            SELECT COUNT(*) FROM {$wpdb->prefix}posts AS p
            JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
            WHERE p.post_type = 'shop_order'
            AND p.post_status IN ('wc-completed', 'wc-processing')
            AND (
                (pm.meta_key = '_billing_first_name' AND pm.meta_value = %s) OR
                (pm.meta_key = '_shipping_first_name' AND pm.meta_value = %s) OR
                (pm.meta_key = '_billing_address_1' AND pm.meta_value = %s) OR
                (pm.meta_key = '_shipping_address_1' AND pm.meta_value = %s) OR
                (pm.meta_key = '_billing_postcode' AND pm.meta_value = %s) OR
                (pm.meta_key = '_billing_email' AND pm.meta_value = %s) OR
                (pm.meta_key = '_customer_user' AND pm.meta_value = %d)
            )
            AND p.ID != %d
        ", $billing_name, $shipping_name, $billing_address, $shipping_address, $postcode, $email, $customer_id, $order->get_id()));

        if ($existing_orders > 0) {
            update_post_meta($order->get_id(), '_is_new_customer', 'no');
        } else {
            update_post_meta($order->get_id(), '_is_new_customer', 'yes');
        }
    }
}
add_action('check_new_customer_orders', 'check_new_customer_orders');

#### **3. Add Green Dot to WooCommerce Orders Dashboard**

function add_new_customer_indicator_column($columns) {
    $columns['new_customer'] = __('New Customer', 'woocommerce');
    return $columns;
}
add_filter('manage_edit-shop_order_columns', 'add_new_customer_indicator_column');

function show_new_customer_indicator($column, $post_id) {
    if ($column === 'new_customer') {
        $is_new = get_post_meta($post_id, '_is_new_customer', true);
        if ($is_new === 'yes') {
            echo '<span style="color: green; font-size: 20px;">●</span>';
        }
    }
}
add_action('manage_shop_order_posts_custom_column', 'show_new_customer_indicator', 10, 2);

#### **4. Add a Screen Option to Toggle the Indicator**

function register_order_screen_option() {
    add_screen_option('per_page', [
        'label'   => __('Show New Customer Indicator', 'woocommerce'),
        'default' => 1,
        'option'  => 'show_new_customer_indicator'
    ]);
}
add_action('load-edit.php', 'register_order_screen_option');

function filter_orders_by_new_customers($query) {
    if (isset($_GET['show_new_customer_indicator']) && $_GET['show_new_customer_indicator'] === '1') {
        $query->set('meta_query', array(
            array(
                'key'   => '_is_new_customer',
                'value' => 'yes',
            )
        ));
    }
}
add_action('pre_get_posts', 'filter_orders_by_new_customers');

### **How It Works**
1. The **scheduled task** (`check_new_customer_orders`) runs every hour and checks new orders.
2. If an order has no previous matches based on billing/shipping name, email, address, and postcode, it is marked as a **new customer** with a `_is_new_customer` meta key.
3. In the **WooCommerce Orders Dashboard**, a **green dot** appears in the new column if an order belongs to a new customer.
4. An **admin screen option** allows enabling/disabling this feature dynamically.

### **Performance Considerations**
– **Efficient Queries:** The SQL query checks relevant meta fields with indexes to reduce load.
– **Background Processing:** The check runs in the background using `wp_schedule_event()` to prevent slowing down the checkout process.
– **Caching:** If you use object caching (like Redis), this will be even more efficient.

Would you like any modifications, such as running the task in real-time instead of a scheduled event? 🚀

Assistant
If you want to check for previous orders **immediately** whenever a new order is placed, instead of relying on a scheduled task, you can hook into WooCommerce’s `woocommerce_checkout_order_processed` action.

### **Real-Time Order Check Implementation**
Replace the scheduled task with this code in your child theme’s `functions.php` or a custom plugin:

function check_new_customer_on_order_create($order_id, $posted_data, $order) {
    if (!$order_id) return;

    $billing_name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
    $shipping_name = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
    $billing_address = $order->get_billing_address_1();
    $shipping_address = $order->get_shipping_address_1();
    $postcode = $order->get_billing_postcode();
    $email = $order->get_billing_email();
    $customer_id = $order->get_customer_id();

    global $wpdb;
    $existing_orders = $wpdb->get_var($wpdb->prepare("
        SELECT COUNT(*) FROM {$wpdb->prefix}posts AS p
        JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        WHERE p.post_type = 'shop_order'
        AND p.post_status IN ('wc-completed', 'wc-processing')
        AND (
            (pm.meta_key = '_billing_first_name' AND pm.meta_value = %s) OR
            (pm.meta_key = '_shipping_first_name' AND pm.meta_value = %s) OR
            (pm.meta_key = '_billing_address_1' AND pm.meta_value = %s) OR
            (pm.meta_key = '_shipping_address_1' AND pm.meta_value = %s) OR
            (pm.meta_key = '_billing_postcode' AND pm.meta_value = %s) OR
            (pm.meta_key = '_billing_email' AND pm.meta_value = %s) OR
            (pm.meta_key = '_customer_user' AND pm.meta_value = %d)
        )
        AND p.ID != %d
    ", $billing_name, $shipping_name, $billing_address, $shipping_address, $postcode, $email, $customer_id, $order_id));

    if ($existing_orders > 0) {
        update_post_meta($order_id, '_is_new_customer', 'no');
    } else {
        update_post_meta($order_id, '_is_new_customer', 'yes');
    }
}
add_action('woocommerce_checkout_order_processed', 'check_new_customer_on_order_create', 10, 3);

### **How This Works**
– Runs **immediately** when a new order is placed.
– Checks the order details against existing orders **before marking it as new or

User
No I just want to check whenever new orders done in front end
Assistant
If you want to check for duplicate customer details **whenever a new order is placed from the front end**, you should use the `woocommerce_checkout_order_processed` action. This ensures the check happens **right after** an order is placed.

### **Real-Time Duplicate Customer Check for Frontend Orders**
Add this to your **child theme’s `functions.php`** or a custom plugin:

function check_new_customer_on_order_create($order_id, $posted_data, $order) {
    if (!$order_id || is_admin()) return; // Ensure it only runs for frontend orders

    $billing_name    = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
    $shipping_name   = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
    $billing_address = $order->get_billing_address_1();
    $shipping_address = $order->get_shipping_address_1();
    $postcode        = $order->get_billing_postcode();
    $email           = $order->get_billing_email();
    $customer_id     = $order->get_customer_id();

    global $wpdb;
    $existing_orders = $wpdb->get_var($wpdb->prepare("
        SELECT COUNT(*) FROM {$wpdb->prefix}posts AS p
        JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        WHERE p.post_type = 'shop_order'
        AND p.post_status IN ('wc-completed', 'wc-processing')
        AND (
            (pm.meta_key = '_billing_first_name' AND pm.meta_value = %s) OR
            (pm.meta_key = '_shipping_first_name' AND pm.meta_value = %s) OR
            (pm.meta_key = '_billing_address_1' AND pm.meta_value = %s) OR
            (pm.meta_key = '_shipping_address_1' AND pm.meta_value = %s) OR
            (pm.meta_key = '_billing_postcode' AND pm.meta_value = %s) OR
            (pm.meta_key = '_billing_email' AND pm.meta_value = %s) OR
            (pm.meta_key = '_customer_user' AND pm.meta_value = %d)
        )
        AND p.ID != %d
    ", $billing_name, $shipping_name, $billing_address, $shipping_address, $postcode, $email, $customer_id, $order_id));

    if ($existing_orders > 0) {
        update_post_meta($order_id, '_is_new_customer', 'no');
    } else {
        update_post_meta($order_id, '_is_new_customer', 'yes');
    }
}
add_action('woocommerce_checkout_order_processed', 'check_new_customer_on_order_create', 10, 3);

### **How This Works**
✅ **Runs Only for Frontend Orders**
– The `is_admin()` check ensures it doesn’t run for admin-created orders.

✅ **Checks Order Details Against Past Orders**
– Compares the billing/shipping name, address, postcode, email, and customer account.
– If a match is found, sets `_is_new_customer = no`, otherwise `_is_new_customer = yes`.

✅ **Executes Immediately After an Order is Placed**
– Uses `woocommerce_checkout_order_processed` to perform the check in real time.

Would you like this data to be displayed somewhere in the order admin panel? 🚀

User
but make this woocommerce_new_order
Assistant
If you want the check to run **only when a new order is placed from the frontend** and use `woocommerce_new_order`, you can update the code accordingly.

### **Updated Code Using `woocommerce_new_order`**
Add this to your **child theme’s `functions.php`** or a custom plugin:

function check_new_customer_on_new_order($order_id) {
    if (!$order_id || is_admin()) return; // Ensure it runs only for frontend orders

    $order = wc_get_order($order_id);
    if (!$order) return;

    $billing_name    = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
    $shipping_name   = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
    $billing_address = $order->get_billing_address_1();
    $shipping_address = $order->get_shipping_address_1();
    $postcode        = $order->get_billing_postcode();
    $email           = $order->get_billing_email();
    $customer_id     = $order->get_customer_id();

    global $wpdb;
    $existing_orders = $wpdb->get_var($wpdb->prepare("
        SELECT COUNT(*) FROM {$wpdb->prefix}posts AS p
        JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        WHERE p.post_type = 'shop_order'
        AND p.post_status IN ('wc-completed', 'wc-processing', 'wc-on-hold', 'wc-pending', 'wc-refunded')
        AND (
            (pm.meta_key = '_billing_first_name' AND pm.meta_value = %s) OR
            (pm.meta_key = '_shipping_first_name' AND pm.meta_value = %s) OR
            (pm.meta_key = '_billing_address_1' AND pm.meta_value = %s) OR
            (pm.meta_key = '_shipping_address_1' AND pm.meta_value = %s) OR
            (pm.meta_key = '_billing_postcode' AND pm.meta_value = %s) OR
            (pm.meta_key = '_billing_email' AND pm.meta_value = %s") OR
            (pm.meta_key = '_customer_user' AND pm.meta_value = %d)
        )
        AND p.ID != %d
    ", $billing_name, $shipping_name, $billing_address, $shipping_address, $postcode, $email, $customer_id, $order_id));

    if ($existing_orders > 0) {
        update_post_meta($order_id, '_is_new_customer', 'no');
    } else {
        update_post_meta($order_id, '_is_new_customer', 'yes');
    }
}
add_action('woocommerce_new_order', 'check_new_customer_on_new_order', 10, 1);

### **How This Works**
✅ **Runs Only for Frontend Orders**
– The `is_admin()` check ensures it doesn’t run for orders created via the admin panel.

✅ **Uses `woocommerce_new_order`**
– Triggers when a new order is placed, ensuring the check runs for **new** orders only.

✅ **Checks Against Past Orders**
– Looks for matches in billing/shipping name, address, postcode, email, or account.
– If a match is found, marks `_is_new_customer = no`, otherwise `_is_new_customer = yes`.

Would you like this status displayed in the **WooCommerce Orders List** with a green dot for new customers? 🎯

Leave a Comment

Your email address will not be published. Required fields are marked *