I need to change the status of my orders to (Cancelled) automatically after 7 days if it is not processed.
I need to change the status from: New Request to Cancelled.
Or
I need to change the status from: Processing to Cancelled.
Thanks
Adnan
I did that with the help of this code:
function autocancel_wc_orders(){
$query = ( array(
'limit' => 10,
'orderby' => 'date',
'order' => 'DESC',
'status' => array( 'wc-pending', 'wc-ywraq-new', 'wc-ywraq-
pending')
) );
$orders = wc_get_orders( $query );
foreach( $orders as $order ){
$date = new DateTime( $order->get_date_created() );
$today = new DateTime();
$interval = $date->diff($today);
$datediff = $interval->format('%a');
if( $datediff > 2 ){
$order->update_status('cancelled', 'Cancelled for missing
payment');
}
}
}
add_action( 'admin_init', 'autocancel_wc_orders' );
I found this answer online in the link:
https://samuelsilva.pt/cancel-woocommerce-not-paid-orders-automatically/
Helpful documentation - https://developer.wordpress.org/reference/classes/wp_query/#date-parameters
https://woocommerce.wp-a2z.org/oik_api/wc_get_order_statuses/
//My server cronjob is targeting wp-cron.php
function ss_cancel_failed_orders() {
$held_duration = 15; //minutes how often my cron job to run per day/hour
$data_store = WC_Data_Store::load('order');
//Change post_status for desired order statuses
//Change date_query before value to desired time compare with modified post date
$unpaid_orders = get_posts(array('posts_per_page' => -1, 'post_type' => 'shop_order', 'post_status' => array('wc-failed','wc-on-hold'), 'date_query' => array(array('before' => '15 minutes ago', 'column'=>'post_modified' ))));
if ( $unpaid_orders ) {
foreach ( $unpaid_orders as $unpaid_order ) {
$order = wc_get_order( $unpaid_order );
$order->update_status( 'cancelled', __( 'Order has expired.', 'woocommerce' ) ); // Status here is without wc- prefix
}
}
wp_clear_scheduled_hook( 'ssa_cancel_failed_orders' );
wp_schedule_single_event( time() + ( absint( $held_duration ) * 60 ), 'ssa_cancel_failed_orders' ); // you can remove wp cron and work with server cron only
}
add_action('ssa_cancel_failed_orders', 'ss_cancel_failed_orders');
Related
I have a custom date field, added with ACF, for each of my products at which point the product status should change to draft.
I know there are a bunch of schedular and count time plugins, but it comes with a bell and whistle I don't need. Is there a simple way to achieve this
Thank you
You can use WorsPress CRON. You can use wp_schedule_event. You have to get all products and get your ACF field to compare against today or current date then use the wp_update_post function to update posts status. try the below code.
// Schedule an action if it's not already scheduled
if ( ! wp_next_scheduled( 'check_daily_for_change_product_status' ) ) {
wp_schedule_event( time(), 'daily', 'check_daily_for_change_product_status' );
}
// Hook into that action that'll fire every three minutes
add_action( 'check_daily_for_change_product_status', 'check_daily_for_change_product_status_func' );
function check_daily_for_change_product_status_func() {
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'post_status' => 'publish'
);
$get_products = new WP_Query( $args );
if( $get_products->have_posts() ){ while ( $get_products->have_posts() ) { $get_products->the_post();
$draft_date = strtotime( get_field('keyname', get_the_ID() ) );
$current_date = time();
if( $current_date >= $draft_date ){
$my_post = array(
'ID' => get_the_ID(),
'post_status' => 'draft',
);
wp_update_post( $my_post );
}
} wp_reset_postdata(); }
}
I want to get the slug of each product in a woocommerce order/purchase of current user.
Steps i took
1.I fetched current user's order.
2.Then I get items/products from the order
$args = array(
'customer_id' => $user->ID
'status' => 'completed'
);
//getting the orders
$orders = wc_get_orders($args);
$orderInfo = [
'id' => [],
'name' => [],
'slug' => []
];
foreach($orders as $order){
foreach( $order->get_items() as $item_id => $item ){
array_push( $orderInfo['id'], $item->get_product_id() );
array_push( $orderInfo['name'], $item->get_name() );
array_push( $orderInfo['slug'], $item->get_slug() );
}
}
After fetching products i am able to get product id and name. But when using $item->get_slug, I am facing this error.
Fatal error: Uncaught Error: Call to undefined method
WC_Order_Item_Product::get_slug()
What wrong am i doing?
You should try this
$product = get_post( $item->get_product_id() );
$slug = $product->post_name;
array_push( $orderInfo['slug'], $slug );
I'd like to show posts from a category first in the homepage and then continue the default order of WordPress posts.
Is it even possible?
I've tried using 2 loops and filter the first one with the category that I want however I don't think that the pagination will work as expected.
Try this (untested code, though).
$total_posts_to_display = 10; // Change accordingly
$id_of_category_1 = 4; // Change accordingly
$filtered_posts = array(); // Array to be filled in with all posts, ordered by "category 1" first
$posts_in_category_1 = get_posts( array(
'numberposts' => $total_posts_to_display,
'category' => $id_of_category_1
) );
$ramaining_posts_number = $total_posts_to_display - count( $posts_in_category_1 );
if ( $ramaining_posts_number > 1 ) {
$excluded_post_ids = array();
foreach( $posts_in_category_1 as $ep ) {
array_push( $excluded_post_ids, $ep->ID );
}
$remaining_posts = get_posts( array(
'numberposts' => $ramaining_posts_number,
'exclude' => $excluded_post_ids
) );
} else {
$remaining_posts = array();
}
$filtered_posts = array_merge( $posts_in_category_1, $remaining_posts );
I have a more sophisticated solution that will support pagination too! You will need to place it in functions.php:
add_action( 'pre_get_posts', 'my_custom_home_post_ordering' );
function my_custom_home_post_ordering( $query ) {
if ( ! is_home() ) {
return;
}
if ( ! $query->is_main_query() ) {
return;
}
$posts_in_category_1 = get_posts( array(
'posts_per_page' => -1,
'category' => 4 // Change accordingly. You may also use 'category_name', instead.
'fields' => 'ids'
) );
$query->set( 'post__in', $posts_in_category_1 );
$query->set( 'orderby', 'post__in' );
}
I have a wordpress site where users can upload products. The default product status is pending,however I want to change it to published if it has passed 12 hours after the post_time.
I am using woocommerce.
I´ve tried to use wp_insert_post_data:
function reset_post_date_wpse_121565($data,$postarr) {
if ($data['post_type'] == 'product'){
$data['post_date'] = '2018-06-03 22:50:00';
}
return $data;
}
add_filter('wp_insert_post_data','reset_post_date_wpse_121565');
But it sets the post to published, what can I do to accomplish this auto update?
You can try WordPress Cron run to achieve this,
function myprefix_custom_cron_schedule( $schedules ) {
$schedules['every_tewlve_hours'] = array(
'interval' => 43200, // Every 12 hours
'display' => __( 'Every 12 hours' ),
);
return $schedules;
}
add_filter( 'cron_schedules', 'myprefix_custom_cron_schedule' );
//Schedule an action if it's not already scheduled
if ( ! wp_next_scheduled( 'myprefix_cron_hook' ) ) {
wp_schedule_event( time(), 'every_tewlve_hours', 'myprefix_cron_hook' );
}
///Hook into that action that'll fire every six hours
add_action( 'myprefix_cron_hook', 'myprefix_cron_function' );
//create your function, that runs on cron
function myprefix_cron_function() {
$args = array(
'numberposts' => -1,
'post_type' => 'product',
'post_status' => array( 'pending' ),
'author' => $userid
);
$pending_posts = get_posts( $args );
//update status code
}
Hope this will helps you.
For more example visit,
wp cron demo
According to the API : http://woocommerce.github.io/woocommerce-rest-api-docs/#list-all-products we can filter products by a single attribute. But Is it impossible to search by multiple attributes through API ?
Example : "I want red shirts". Here attribute is color and attribute term is red. To accomplish the search, the query string goes like this : products?category=17&attribute=pa_color&attribute_term=22&
And we get the red shirts only.
But for "I want red medium shirts" , here an additional size attribute with value medium is encountered. And according to the API there is no way to associate both the color and the size attributes in the query string. So the query -
products?category=17&attribute=pa_color&attribute_term=22&attribute=pa_size&attribute_term=24&
returns all products from the store
Is there any workaround ?
I have written custom query that does it all :D
This is a callback function. All you need to do is create new endpoint with this callback:
Here is a documentation:
category - string (category slug) - filter by products category.
per_page - int (default - from admin) - show items on one page.
offset - int (default - 1) - show page number.
order - string (ASC/DESC, default: desc) - order products ascending or descending.
orderby - string (name, price, default: name) - order products by key.
filter - array
[pa_attribute_name (string) ] = array of ID's.
[min_price (string) ] = int.
[max_price (string) ] = int.
Example:
/wp-json/go/v1/products/?category=smartphones&filter[pa_brand]=87,88&filter[pa_colour]=17&filter[min_price]=1&filter[max_price]=50&per_page=10&offset=1&order=DESC&orderby=price
Here is a function:
public function get_products_list_callback( \WP_REST_Request $request ) {
$params = $request->get_params();
$category = General_Helper::get_array_value( 'category', $params );
$filters = General_Helper::get_array_value( 'filter', $params );
$per_page = General_Helper::get_array_value( 'per_page', $params );
$offset = General_Helper::get_array_value( 'offset', $params );
$order = General_Helper::get_array_value( 'order', $params );
$orderby = General_Helper::get_array_value( 'orderby', $params );
$output = [];
// Use default arguments.
$args = [
'post_type' => Config::POST_TYPE_SLUG_PRODUCT,
'posts_per_page' => get_option( 'posts_per_page' ),
'post_status' => 'publish',
'paged' => 1,
];
// Posts per page.
if ( ! empty( $per_page ) ) {
$args['posts_per_page'] = $per_page;
}
// Pagination, starts from 1.
if ( ! empty( $offset ) ) {
$args['paged'] = $offset;
}
// Order condition. ASC/DESC.
if ( ! empty( $order ) ) {
$args['order'] = $order;
}
// Orderby condition. Name/Price.
if ( ! empty( $orderby ) ) {
if ( $orderby === 'price' ) {
$args['orderby'] = 'meta_value_num';
} else {
$args['orderby'] = $orderby;
}
}
// If filter buy category or attributes.
if ( ! empty( $category ) || ! empty( $filters ) ) {
$args['tax_query']['relation'] = 'AND';
// Category filter.
if ( ! empty( $category ) ) {
$args['tax_query'][] = [
'taxonomy' => Config::TAXONOMY_SLUG_PRODUCT,
'field' => 'slug',
'terms' => [ $category ],
];
}
// Attributes filter.
if ( ! empty( $filters ) ) {
foreach ( $filters as $filter_key => $filter_value ) {
if ( $filter_key === 'min_price' || $filter_key === 'max_price' ) {
continue;
}
$args['tax_query'][] = [
'taxonomy' => $filter_key,
'field' => 'term_id',
'terms' => \explode( ',', $filter_value ),
];
}
}
// Min / Max price filter.
if ( isset( $filters['min_price'] ) || isset( $filters['max_price'] ) ) {
$price_request = [];
if ( isset( $filters['min_price'] ) ) {
$price_request['min_price'] = $filters['min_price'];
}
if ( isset( $filters['max_price'] ) ) {
$price_request['max_price'] = $filters['max_price'];
}
$args['meta_query'][] = \wc_get_min_max_price_meta_query( $price_request );
}
}
$the_query = new \WP_Query( $args );
if ( ! $the_query->have_posts() ) {
return $output;
}
while ( $the_query->have_posts() ) {
$the_query->the_post();
$output[] = get_the_title();
}
wp_reset_postdata();
return $output;
}
Hope it helps
Try to request like this:
products?attribute=pa_color&attribute_term=51,50&per_page=100
Its worked for me.
Latest woocommerce-api wc/v2!
after test on WooRest API v3, you can pass multiple term taxonomy IDs.
You have to pass a string with ids separated by comma, this will be parsed as an array by WooRest API v3.
Like this :
/wp-json/wc/v3/products/?category=1,2,3,4
Don't forget to encode query parameter or use Automattic\WooCommerce package
Enjoy,
I just looked into the woocommerce rest api implementation at
plugins/woocommerce/includes/api/class-wc-rest-products-controller.php
file but unfortunately their codes doesn't support multiple attributes.
But you can write your own query to achieve your goal.
$args = array(
'post_type' => 'product',
'tax_query' => array(
array(
'relation' => 'AND',
array(
'taxonomy' => 'pa_color',
'field' => 'term_id',
'terms' => array( 'red' ),
),
array(
'taxonomy' => 'pa_size',
'field' => 'term_id',
'terms' => array( 'Long' ),
),
),
),
);
$products = new WP_Query( $args );
print_r($products);