WooCommerce Order Status Customization

User
add_action( 'woocommerce_order_status_dispensing', 'woocommerce_completed_order_invoice_date_issued' );
function woocommerce_completed_order_invoice_date_issued( $order_id ) {

global $wpdb,$woocommerce;
$order = new WC_Order( $order_id );
$order_status = is_callable( array( $order, 'get_status' ) ) ? $order->get_status() : $order->order_status;
if ( $order_status == 'dispensing' ) {
update_post_meta( $order_id,'_dispensed_date',date("Y-m-d"));
}

}
add_action( 'admin_action_mark_dispensing', 'bulk_process_dispensing_status' );
function bulk_process_dispensing_status() {
if( !isset( $_REQUEST['post'] ) && !is_array( $_REQUEST['post'] ) )
return;

foreach( $_REQUEST['post'] as $order_id ) {
$user_id = get_current_user_id();
update_post_meta($order_id,'_prescriber_id',$user_id);
}
}
explain above query

Assistant
The code provided adds custom actions in WooCommerce to handle order status updates and bulk actions. Below is a detailed explanation of each part:

### 1. **`add_action( 'woocommerce_order_status_dispensing', 'woocommerce_completed_order_invoice_date_issued' );`**
– **Purpose**: Hooks into the `woocommerce_order_status_dispensing` action, which triggers when an order's status changes to `dispensing`.
– **Callback**: `woocommerce_completed_order_invoice_date_issued`
– **Functionality**:
– It retrieves the order ID and the current order object using `WC_Order`.
– Checks if the order's status is `dispensing`.
– If true, it updates the order's meta field `_dispensed_date` with the current date (format: `Y-m-d`).

### 2. **Function: `woocommerce_completed_order_invoice_date_issued`**
– **Parameters**:
– `$order_id`: The ID of the order whose status has changed to `dispensing`.
– **Global Variables**:
– `$wpdb`: The WordPress database object (not used directly in the function).
– `$woocommerce`: The WooCommerce global object (also not used directly).
– **Key Actions**:
– **Retrieve Order Status**:
– `get_status()` checks the order's status. If not callable, it falls back to the deprecated `order_status`.
– **Update Metadata**:
– If the status is `dispensing`, it updates the `_dispensed_date` meta key with today's date.

### 3. **`add_action( 'admin_action_mark_dispensing', 'bulk_process_dispensing_status' );`**
– **Purpose**: Hooks into the `admin_action_mark_dispensing` action, which is triggered for a custom bulk action in the WordPress admin.
– **Callback**: `bulk_process_dispensing_status`
– **Functionality**:
– **Checks Input**: Validates that `$_REQUEST['post']` is set and is an array. If not, the function exits.
– **Loops Through Selected Orders**:
– Iterates over the order IDs in `$_REQUEST['post']`.
– For each order ID, it:
– Retrieves the current admin user's ID using `get_current_user_id()`.
– Updates the order meta `_prescriber_id` with the current user's ID.

### How These Actions Work Together:
1. **Order Status Update**:
– When an order's status changes to `dispensing`, the `_dispensed_date` meta field is updated with the current date.
2. **Admin Bulk Action**:
– In the admin panel, a bulk action `mark_dispensing` can be applied to selected orders.
– This action sets the `_prescriber_id` meta field of the orders to the current admin user's ID.

### Practical Use Case:
– **Tracking Dispensed Date**:
– By setting `_dispensed_date` when an order's status changes to `dispensing`, you can keep a record of when the order was processed as dispensed.
– **Bulk Update of Prescriber ID**:
– The custom bulk action allows assigning a prescriber (identified by their user ID) to multiple orders at once, streamlining the process for admins.

Let me know if you need further clarification!

User
its causing timeout when upto 50 orders selected
Assistant
The timeout issue occurs because the `bulk_process_dispensing_status` function is processing orders in a synchronous loop, and if the selected number of orders is large (e.g., 50), the execution time increases significantly. This can exceed PHP's `max_execution_time` or server resources.

Here are strategies to optimize the function and prevent timeouts:

### 1. **Process Orders in Smaller Batches**
Instead of processing all orders at once, split the process into smaller batches. You can achieve this using JavaScript or enqueue jobs in the background.

#### Solution: Use `wp_schedule_single_event` for Background Processing

add_action('admin_action_mark_dispensing', 'bulk_process_dispensing_status');
function bulk_process_dispensing_status() {
    if (!isset($_REQUEST['post']) || !is_array($_REQUEST['post'])) {
        return;
    }

    // Schedule the batch job
    $order_ids = $_REQUEST['post'];
    update_option('bulk_dispensing_orders', $order_ids);

    wp_schedule_single_event(time() + 5, 'process_bulk_dispensing_in_batches');
    wp_redirect(admin_url('edit.php?post_type=shop_order&message=batch_processing_started'));
    exit;
}

add_action('process_bulk_dispensing_in_batches', 'process_bulk_dispensing_in_batches');
function process_bulk_dispensing_in_batches() {
    $order_ids = get_option('bulk_dispensing_orders', []);
    $batch_size = 10; // Number of orders per batch
    $user_id = get_current_user_id();

    if (!empty($order_ids)) {
        for ($i = 0; $i < $batch_size && !empty($order_ids); $i++) {
            $order_id = array_shift($order_ids);
            update_post_meta($order_id, '_prescriber_id', $user_id);
        }
        update_option('bulk_dispensing_orders', $order_ids);

        // Reschedule if orders remain
        if (!empty($order_ids)) {
            wp_schedule_single_event(time() + 5, 'process_bulk_dispensing_in_batches');
        }
    } else {
        delete_option('bulk_dispensing_orders');
    }
}

### 2. **Increase Server Limits Temporarily**
If the bulk action isn't frequent, you can temporarily increase PHP settings:
– **`php.ini`**:

max_execution_time = 300
  memory_limit = 512M

– Or set these in your WordPress `.htaccess`:

php_value max_execution_time 300
  php_value memory_limit 512M

This is not a long-term solution but may help when processing larger orders.

### 3. **Optimize the Loop with Fewer Operations**
Currently, the loop performs an update for each order. Combining updates or reducing operations can help:
– Update all orders in a single database query:

add_action('admin_action_mark_dispensing', 'bulk_process_dispensing_status');
function bulk_process_dispensing_status() {
    if (!isset($_REQUEST['post']) || !is_array($_REQUEST['post'])) {
        return;
    }

    global $wpdb;
    $order_ids = array_map('intval', $_REQUEST['post']);
    $user_id = get_current_user_id();

    // Use a single query for efficiency
    $placeholders = implode(',', array_fill(0, count($order_ids), '%d'));
    $query = $wpdb->prepare(
        "UPDATE {$wpdb->postmeta} SET meta_value = %d WHERE meta_key = '_prescriber_id' AND post_id IN ($placeholders)",
        array_merge([$user_id], $order_ids)
    );

    $wpdb->query($query);

    wp_redirect(admin_url('edit.php?post_type=shop_order&message=success'));
    exit;
}

### 4. **Use AJAX for Incremental Updates**
Break down the operation using AJAX to handle chunks of orders asynchronously:
– Add a JavaScript script to process batches of orders via AJAX.
– Update server-side logic to accept partial requests and process them incrementally.

### Recommendation
If the task involves processing large amounts of data, **asynchronous processing** (background jobs or AJAX) is the most efficient and scalable solution. If you need help implementing any of these solutions, let me know!

User
We are now continuing development mode on Cloudflare.
If possible, please can order state change process from awaiting prescription to dispensing
Correct above sentence
Assistant
We are now continuing to use Development Mode on Cloudflare.
If possible, please enable the order state change process from **Awaiting Prescription** to **Dispensing**.
User
As we are now bypassing edge cache,
Is backend order status change issue also resolved, which were given timeout?
Correct above sentence
Assistant
As we are now bypassing the edge cache,
is the backend order status change issue, which was causing timeouts, also resolved?

Leave a Comment

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