I wanted to know how to automatically delete an order when a user ordering a Specific product/category if it was in pending in 5m.
I have this code but when I add it to my function.php it doesn't work.
function update_order_status( $order_id ) {
$order = new WC_Order( $order_id );
$order_status = $order->get_status();
if ('pending' == $order_status ) {
$current_time = date('h:i:s');
sleep(600);
wp_delete_post($order_id,true);
}
}
You can use the CRON job and then get all orders with pending status and then check their order date with the current date and delete.
Add custom 5-minute cron schedules by using WC cron_schedules hook
function add_five_minute_cron_schedules($schedules){
if( !isset( $schedules["five_minute"] ) ){
$schedules["five_minute"] = array(
'interval' => 5*60,
'display' => __('Once every 5 minutes')
);
}
return $schedules;
}
add_filter('cron_schedules','add_five_minute_cron_schedules');
Scheduled your CRON on WP init Hook.
if( ! wp_next_scheduled( 'remove_pending_order_after_five_minute' ) ){
wp_schedule_event( time(), 'five_minute', 'remove_pending_order_after_five_minute' );
}
//Hook into that action that'll fire every 5 minutes.
add_action( 'remove_pending_order_after_five_minute', 'remove_pending_order_after_five_minute_callback' );
function remove_pending_order_after_five_minute_callback(){
// get all pending orders that created in the last 5 minutes.
$args = array(
'post_status' => array( 'wc-processing', 'wc-pending', 'wc-on-hold' ),
'date_created' => '<' . ( time() - 300 ),
'posts_per_page' => -1
);
$orders = wc_get_orders($args);
if( !empty( $orders ) ){
// Loop through each $order objects.
foreach( $orders as $order ){
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
$order = wc_get_order( $order_id );
if ( $order && sizeof( $order->get_items() ) > 0 ) {
foreach( $order->get_items() as $item ) {
if( has_term( 'charkh', 'product_cat', $item->get_product_id() ) ) {
wp_delete_post( $order_id );
break;
}
}
}
}
}
}
This code goes to active theme functions.php file. Tested and works.
Related
I'm using a plugin on my WooCommerce site called Codisto. The purpose of the plugin is to consolidate orders from sales channels such as Amazon and eBay into my WooCommerce dashboard for better visibility and order management.
Upon order import into my WooCommerce dashboard I would like my Amazon orders to automatically be assigned a status of "Amazon". I have created the custom status however have been unable to properly code a solution that can correctly recognize the order and auto assign the custom status.
Here is my code:
if ( 'processing' && ( 'on-hold' === $order->status || 'pending' === $order->status || 'failed' === $order->status ) ) {
$has_amazon_order = false;
foreach ( $order->get_order_id() as $order_id ) {
$order = $order_id->get_order_id();
$amazon_order = get_post_meta( $order_id, '_codisto_amazonorderid', true );
if ( $amazon_order == 'yes' ) {
$has_amazon_order = true;
break;
}
}
if ( $has_amazon_order == 'yes' ) {
$status = 'amazon';
}
}
return $status;
}
add_action( 'woocommerce_payment_complete_order_status', 'rb_wc_set_amazon_order_status_on_import', 20, 3 );
I've been looking at the developer's code and I believe the function is related to the $amazonorderid and $createdby param as referenced here:
if ( ! $order_id ) {
$new_order_data_callback = array( $this, 'order_set_date' );
add_filter( 'woocommerce_new_order_data', $new_order_data_callback, 1, 1 );
$createdby = 'eBay';
if ( $amazonorderid ) {
$createdby = 'Amazon';
}
$order = wc_create_order( array( 'customer_id' => $customer_id, 'customer_note' => $customer_note, 'created_via' => $createdby ) );
remove_filter( 'woocommerce_new_order_data', $new_order_data_callback );
$order_id = $order->get_id();
update_post_meta( $order_id, '_codisto_orderid', (int)$ordercontent->orderid );
update_post_meta( $order_id, '_codisto_merchantid', (int)$ordercontent->merchantid );
if ( $amazonorderid ) {
update_post_meta( $order_id, '_codisto_amazonorderid', $amazonorderid );
Any and all suggestions are greatly appreciated!
I am trying to update a product meta for all products of each order that gets completed. Can you have a look at my approach below? Any help on why it is not working will be appreciated. I am new to all this php customizing.
add_action( 'woocommerce_order_status_completed', 'update_product_meta', 20, 2 );
function update_product_meta ( $order_id, $order ) {
// GET USER ORDERS (COMPLETED + PROCESSING)
$args = array(
'post_status' => array('wc-completed')
);
$done_orders = wc_get_orders( $args );
// LOOP THROUGH ORDERS AND GET PRODUCT IDS
if ( $done_orders ) {
$product_ids = array();
foreach ( $done_orders as $done_order ) {
$order = wc_get_order( $done_order->ID );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
}
}
add_action( 'woocommerce_process_product_meta', 'action_save_product_meta' );
function action_save_product_meta( $product_id ) {
update_post_meta($product_id, 'Stav', 'Vypůjčeno' );
}
}
}
Well you're pretty close, you just have to remove the nonsense at the end.
Something along the lines of:
<?php
add_action( 'woocommerce_order_status_completed', function ( $order_id, $order ) {
$args = array(
'post_status' => array('wc-completed')
);
$done_orders = wc_get_orders( $args );
if ( ! empty( $done_orders ) ) {
foreach ( $done_orders as $done_order ) {
$order = wc_get_order( $done_order->ID );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
update_post_meta( $product_id, 'Stav', 'Vypůjčeno' );
};
};
};
}, 20, 2 );
You should think of limiting it to a specific amount because right now your query will request ALL items ever completed. be careful.
I'm trying to add in a feature where an admin order note will be added for all first time customers.
The code I am trying is:
add_action('woocommerce_thankyou', 'is_returning_customer', 10, 1);
function is_returning_customer($order_id)
{
if (!$order_id) {
return;
}
if(is_user_logged_in()) {
$order_status = array('wc-on-hold,','wc-processing', 'wc-completed');
$customer_id = get_current_user_id();
$customer_orders=get_posts( array(
'meta_key' => '_customer_user',
'meta_value' => $customer_id,
'post_type' => 'shop_order',
'post_status' => $order_status,
'numberposts' => -1
)
);
}
if (count($customer_orders) => 1) {
$order = wc_get_order( $order_id );
$note = '*** New Customer ***';
$order->add_order_note($note);
$order->save();
}
}
However, the problem it's adding the new customer note on every order. Any advice?
Your code looks fine except for syntax errors here. I revised your code. try the below code.
Changed
if (count($customer_orders) => 1) {
To
if (count($customer_orders) >= 1) {
Changed
$order_status = array( 'wc-on-hold,','wc-processing', 'wc-completed' );
To
$order_status = array( 'wc-on-hold', 'wc-processing', 'wc-completed' );
for check customer is first time trying below condition.
if ( count( $customer_orders ) < 1 ) {
for check customer is a return. try the below condition.
if ( count( $customer_orders ) > 0 ) {
Complete code. for returning customer
function is_returning_customer( $order_id ) {
if ( !$order_id ) {
return;
}
if( is_user_logged_in() ) {
$order_status = array( 'wc-on-hold,','wc-processing', 'wc-completed' );
$customer_id = get_current_user_id();
$customer_orders = get_posts( array(
'meta_key' => '_customer_user',
'meta_value' => $customer_id,
'post_type' => 'shop_order',
'post_status' => $order_status,
'numberposts' => -1
)
);
}
if ( count( $customer_orders ) > 0 ) {
$order = wc_get_order( $order_id );
$note = '*** New Customer ***';
$order->add_order_note($note);
$order->save();
}
}
add_action( 'woocommerce_thankyou', 'is_returning_customer', 10, 1 );
Complete code for first time customer
function is_first_time_customer( $order_id ) {
if ( !$order_id ) {
return;
}
if( is_user_logged_in() ) {
$order_status = array( 'wc-on-hold,','wc-processing', 'wc-completed' );
$customer_id = get_current_user_id();
$customer_orders = get_posts( array(
'meta_key' => '_customer_user',
'meta_value' => $customer_id,
'post_type' => 'shop_order',
'post_status' => $order_status,
'numberposts' => -1
)
);
}
if ( count( $customer_orders ) < 1 ) {
$order = wc_get_order( $order_id );
$note = '*** New Customer ***';
$order->add_order_note($note);
$order->save();
}
}
add_action( 'woocommerce_thankyou', 'is_first_time_customer', 10, 1 );
Actually it is not necessary to go through the orders, as there is already a function for this in WooCommerce, namely wc_get_customer_order_count() - Get total orders by customer.
Only the issue here is, just like with your current code, that this would only work for logged in users.
To make this also work for 'guests' you can use the following:
function action_woocommerce_thankyou( $order_id ) {
// Get $order object
$order = wc_get_order( $order_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// Get user id
$user_id = $order->get_user_id();
// Set variable
$count = 0;
// Not a guest
if ( $user_id > 0 ) {
// Get the total orders by a customer.
$count = wc_get_customer_order_count( $user_id );
} else {
// Guest 'user', don't have a user id so we will determine the previous orders based on the billing email
// Get billing email
$billing_email = $order->get_billing_email();
if ( ! empty ( $billing_email ) ) {
// Call function
$count = has_guest_bought_by_email( $billing_email );
}
}
// Output
if ( $count == 1 ) {
$note = '** New Customer **';
$order->add_order_note( $note );
}
}
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
// Based on https://stackoverflow.com/a/46216073/11987538
function has_guest_bought_by_email( $email ) {
global $wpdb;
// Get all order statuses.
$order_statuses = array_map( 'esc_sql', array_keys( wc_get_order_statuses() ) );
$results = $wpdb->get_col( "
SELECT p.ID FROM {$wpdb->prefix}posts AS p
INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
WHERE p.post_status IN ( '" . implode( "','", $order_statuses ) . "' )
AND p.post_type LIKE 'shop_order'
AND pm.meta_key = '_billing_email'
AND pm.meta_value = '$email'
" );
// Return result
return count( $results );
}
Related: How to add a first order message after the buyer name in WooCommerce admin order list
I have two scripts that are interfering with each other. What I need for this website is that: all successful purchases should go to page https://aefcoaching.com/gracias-por-tu-compra, except successful purchase of Product ID 1813, which should go to https://aefcoaching.com/gracias-gimnasio-mental/
/* # Redirect to the Thank You page after successful payment in WooCommerce */
if( !function_exists('sc_custom_redirect_after_purchase') ):
function sc_custom_redirect_after_purchase() {
global $wp;
if ( is_checkout() && !empty($wp->query_vars['order-received']) ) :
$order_id = absint($wp->query_vars['order-received']);
$order_key = wc_clean($_GET['key']);
$th_page_url = 'https://aefcoaching.com/gracias-por-tu-compra';
$redirect = add_query_arg(
array(
'order' => $order_id,
'key' => $order_key,
), $th_page_url);
wp_safe_redirect($redirect);
exit;
endif;
}
add_action('template_redirect', 'sc_custom_redirect_after_purchase');
endif;
/* # Redirect Gimnasio Mental purchases to a specific Thank You Page */
function action_woocommerce_thankyou( $order_id ) {
if( ! $order_id ) {
return;
}
// Instannce of the WC_Order Object
$order = wc_get_order( $order_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// False
$redirection = false;
// Loop through order items
foreach ( $order->get_items() as $item_key => $item ) {
// Product ID(s)
$product_ids = array( $item->get_product_id(), $item->get_variation_id() );
// Product ID in array
if ( in_array( 1813, $product_ids ) ) {
$redirection = true;
}
}
}
// Make the custom redirection when a targeted product has been found in the order
if ( $redirection ) {
wp_safe_redirect( home_url( '/gracias-gimnasio-mental/' ) );
exit;
}
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
The first piece works great. The second doesn't because of the first one. I'm not sure how to integrate these two rather than have 2 separate codes. Can you help me?
Please merge the two logics into one , by changing your sc_custom_redirect_after_purchase function into the following:
function sc_custom_redirect_after_purchase() {
global $wp;
if ( is_checkout() && !empty($wp->query_vars['order-received']) ) :
$order_id = absint($wp->query_vars['order-received']);
$order_key = wc_clean($_GET['key']);
$th_page_url = 'https://aefcoaching.com/gracias-por-tu-compra';
//////////////////////
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $item_key => $item ) {
// Product ID(s)
$product_ids = array( $item->get_product_id(), $item->get_variation_id() );
// Product ID in array
if ( in_array( 1813, $product_ids ) ) {
// $redirection = true;
$th_page_url = 'https://aefcoaching.com/gracias-gimnasio-mental/';
}
}
/////////////////////
$redirect = add_query_arg(
array(
'order' => $order_id,
'key' => $order_key,
), $th_page_url);
wp_safe_redirect($redirect);
exit;
endif;
}
I need to update the order status of all 'processing' orders after a specific period of time in WooCommerce.
I aimed to do this via cron job. So I added this hook in WP Control, with a weekly schedule: woocommerce_complete_processing_order_weekly
Here is what I added in my functions.php:
add_action( 'woocommerce_complete_processing_order_weekly', 'custom_woocommerce_complete_order', 10, 0 );
function custom_woocommerce_complete_order ( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
}
Could you help me out with this?
add_action( 'admin_init', 'update_order_status_on_monday' );
function update_order_status_on_monday() {
if ( date( 'D', strtotime( 'now' ) ) === 'Mon' && !get_transient( '_updated_order_status_on_monday' ) ) {
$processing_orders = wc_get_orders( $args = array(
'numberposts' => -1,
'post_status' => 'wc-processing',
) );
if ( !empty( $processing_orders ) ) {
foreach ( $processing_orders as $order )
$order->update_status( 'completed' );
}
set_transient( '_updated_order_status_on_monday', true );
} elseif ( date( 'D', strtotime( 'now' ) ) !== 'Mon' ) {
delete_transient( '_updated_order_status_on_monday' );
}
}
Add this code into your active theme functions.php