WooCommerce Order Status Customization
January 22, 2025 ยท AI Conversations
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
—
### 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!
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!
If possible, please can order state change process from awaiting prescription to dispensing
Correct above sentence
If possible, please enable the order state change process from **Awaiting Prescription** to **Dispensing**.
Is backend order status change issue also resolved, which were given timeout?
Correct above sentence
is the backend order status change issue, which was causing timeouts, also resolved?