So I'm new to coding in Wordpress an woocommerce too!
I want to list all completed orders in the front end of a Wordpress site, order number and item ordered.
I have created a template file and I can get it run basic PHP such as echo and foreach, but I can't get my head around how to list completed orders!
however, the below code doesn't return any orders.
I found the commented out SQL statement which is more what I'm after i.e. return all orders that have a date of x in a text meta field. but I have no idea of how to include it in the template file!
<?php
/**
* Template Name: PPR List
*/
wp_head();
Echo "testing";
//"SELECT post_id FROM wp_postmeta WHERE meta_key = 'arrival_date' AND meta_value <= $today"
$all_orders = get_posts( array(
'numberposts' => $order_count,
'post_type' => wc_get_order_types( 'complete' ),
'post_status' => array_keys( wc_get_order_statuses() )
) );
echo '<pre>'; print_r($array); echo '</pre>';
wp_footer();
Using WC_Order_Query is a lighter and simpler way
wc_get_orders and WC_Order_Query provide a standard way of retrieving orders that is safe to use and will not break due to database changes in future WooCommerce versions.
Source: wc_get_orders and WC_Order_Query
So you get
$args = array(
'status' => 'completed', // Accepts a string: one of 'pending', 'processing', 'on-hold', 'completed', 'refunded, 'failed', 'cancelled', or a custom order status.
'meta_key' => 'arrival_date', // Postmeta key field
'meta_value' => $today, // Postmeta value field
'meta_compare' => '<=', // Possible values are ‘=’, ‘!=’, ‘>’, ‘>=’, ‘<‘, ‘<=’, ‘LIKE’, ‘NOT LIKE’, ‘IN’, ‘NOT IN’, ‘BETWEEN’, ‘NOT BETWEEN’, ‘EXISTS’ (only in WP >= 3.5), and ‘NOT EXISTS’ (also only in WP >= 3.5). Values ‘REGEXP’, ‘NOT REGEXP’ and ‘RLIKE’ were added in WordPress 3.7. Default value is ‘=’.
);
$orders = wc_get_orders( $args );
foreach ( $orders as $order ) {
$order_id = $order->get_id();
echo '<p>' . $order_id . '</p>';
}
Might come in handy: How to get WooCommerce order details
Related
I want to display the total number of purchases made on my site to my site users; Previously, I wrote the code that displayed the total number of products published on my site, and now I want the code to display the total number of successful purchases from my site to the user.
The code I wrote to display the number of products on my site is as follows:
function product_count_shortcode() {
$count_posts = wp_count_posts( 'product' );
return $count_posts->publish;
}
add_shortcode( 'product_counthalsho', 'product_count_shortcode' );
You will basically have to show the number of orders that have the status completed. Just create a function that will query the order post_type and with the status completed.
You can simply use get_posts and use the php function count the check how many results you have, or use WP_Query that already has a property in the return object that tells you how many orders you have with that status.
Later Edit:
function mrc_total_completed_orders() {
$args = array(
'post_type' => 'order',
'posts_per_page' => -1,
'post_status' => 'completed',
);
$orders = get_posts( $args );
return count( $orders ); }
Or you can use the WC_Order_Query
function mrc_mrc_total_completed_Orders() {
$query = new WC_Order_Query( array(
'limit' => 99999,
'status' => array( 'completed' ),
'return' => 'ids',
) );
$orders = $query->get_orders();
return count( $orders ); }
Also some documentation here
Note that I haven't tested these solutions, but its enough to get you started :)
Usage:
echo mrc_mrc_total_completed_Orders();
I'm trying to develop a snippet in order to hide out-of-stock products after 10 days when they went sold out.
I'm trying to develop a snippet to hide out-of-stock products after 10 days when they sold out.
For that I was inspired by:
Hide 'out of stock' products in Woocommerce
Change stock email notifications recipient in WooCommerce
I have to build a custom function which will check the out of stock date. But I do not find any value or properties, which stores that date and time on which the product was marked as sold out.
Is there something out of the box available or do I have to create a snipped first to store the date and time when a product is marked as sold out and use that info with a IF statement to hide a product or not based on the days in between.
add_action('woocommerce_product_query', 'custom_woocommerce_product_query');
function custom_woocommerce_product_query($q)
{
if ( out_of_stock < 10 ())
{
$oos_query = new WP_Query(['meta_query' => [['key' => '_stock_status', 'value' => 'outofstock', 'compare' => '=', ], ], 'post_type' => 'product', 'posts_per_page' => - 1, 'fields' => 'ids', ]);
$exclude_ids = $oos_query->posts;
$q->set('post__not_in', $exclude_ids);
}
}
Out of the box "no stock" notification hook
add_filter( 'woocommerce_email_recipient_no_stock', 'change_stock_email_recipient', 10, 2 ); // For No stock notification
Would be glad if someone could point me in the right direction
This will hide out-of-stock products after 10 days when they went sold out.
After stock change events, when the product is without stock woocommerce_no_stock action hook is triggered
When you adjust the stock in WooCommerce backend via the product edit settings, the $meta_value is reset via woocommerce_admin_process_product_object action hook
Change the shop query via woocommerce_product_query action hook
Explanation via comment tags added to my answer:
// After stock change events, when the product is without stock
function action_woocommerce_no_stock( $wc_get_product ) {
// Retrieves the date, in localized format.
$date = wp_date( 'Y-m-d' );
// Update meta
$wc_get_product->update_meta_data( '_no_stock_date', $date );
// Save
$wc_get_product->save();
}
add_action( 'woocommerce_no_stock', 'action_woocommerce_no_stock', 10, 1 );
// When product is saved in WooCommerce backend
function action_woocommerce_admin_process_product_object( $product ) {
// Get stock quantity
$stock_quantity = $product->get_stock_quantity();
// Greater than or equal to
if ( $stock_quantity >= 1 ) {
// Get meta value
$no_stock_date = $product->get_meta( '_no_stock_date' );
// NOT empty
if ( ! empty ( $no_stock_date ) ) {
// Update
$product->update_meta_data( '_no_stock_date', '' );
}
}
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );
// Change the shop query
function action_woocommerce_product_query( $q, $query ) {
// Returns true when on the product archive page (shop).
if ( is_shop() ) {
// Retrieves the date, in localized format.
$date = wp_date( 'Y-m-d' );
// Date - 10 days
$date = wp_date( 'Y-m-d', strtotime( $date . ' -10 days' ) );
// Get any existing meta query
$meta_query = $q->get( 'meta_query' );
// Define an additional meta query
$meta_query[] = array(
'relation' => 'OR',
array(
'key' => '_no_stock_date',
'value' => $date,
'compare' => '>',
'type' => 'date',
),
array(
'key' => '_no_stock_date',
'compare' => 'NOT EXISTS',
'type' => 'date',
)
);
// Set the new merged meta query
$q->set( 'meta_query', $meta_query );
}
}
add_action( 'woocommerce_product_query', 'action_woocommerce_product_query', 10, 2 );
How do I get IDs of all products in one array?
The output should be a simple array containing some numbers, nothing more.
I have been advised against using query_posts(), so I would prefer a solution not using this function.
There is multiple ways to get all product ids in an array:
1) Using Woocommerce WC_Product_Query:
$ids = wc_get_products( array( 'return' => 'ids', 'limit' => -1 ) );
2) Using Wordpress WP_Query (including product variations IDs),
$ids = get_posts( array(
'posts_per_page' => -1,
'post_type' => array('product','product_variation'),
'fields' => 'ids',
) );
3) Using a WPDB (a SQL query) (including product variation IDS):
global $wpdb;
$ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->prefix}posts WHERE post_type IN ('product','product_variation')");
In the 2 last ways you can remove 'product_variation' post type, if you don't want it.
I want to get the processing order count in WooCommerce. I'm using the following code in the Code Snippet plugin but that is working.
if( !function_exists( 'wc_processing_order_count' ) ) {
require_once '../plugins/woocommerce/includes/wc-order-functions.php';
}
// NOTICE! Understand what this does before running.
$result = wc_processing_order_count();
It's returning nothing.
This custom function use a very light SQL query to get the orders count from a specific status:
function get_orders_count_from_status( $status ){
global $wpdb;
// We add 'wc-' prefix when is missing from order staus
$status = 'wc-' . str_replace('wc-', '', $status);
return $wpdb->get_var("
SELECT count(ID) FROM {$wpdb->prefix}posts WHERE post_status LIKE '$status' AND `post_type` LIKE 'shop_order'
");
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Usage example for "processing" orders count:
// Display "processing" orders count
echo get_orders_count_from_status( "processing" );
Both the answers above are way too complicated for something so simple.
Simplest way is this :)
$processing_orders_count = count(wc_get_orders( array(
'status' => 'processing',
'return' => 'ids',
'limit' => -1,
)));
This method could help you. The order is stored as post_type shop_order. So by creating query to get all posts of type shop_order and by passing arguments to get all processing order, you will be able to get those orders
$args = array(
'post_type' => 'shop_order',
'post_status' => 'publish',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'shop_order_status',
'field' => 'slug',
'terms' => array('processing')
)
)
);
$loop = new WP_Query( $args );
while ( $loop->have_posts() ){
$loop->the_post();
$order_id = $loop->post->ID;
$order = new WC_Order($order_id);
}
Take a look at: https://github.com/woocommerce/woocommerce/wiki/wc_get_orders-and-WC_Order_Query
That reference really helped me in a similar situation.
Using the WC functions ensures your code is more future proof compared to using a hardcoded query or WP_Query as mentioned in other answers.
I can't get order objects with status of wc-pending / Pending Payment. It simply returns ALL the order objects:
$my_course_query = new WP_Query( array(
'post_type' => 'shop_order',
'post_status' => 'wc-pending',
'posts_per_page' => -1
) );
Your code Is just working perfectly as expected, in frontend, I have test it and it output only orders with **pending status. So I can't tell what is your issue as your question is not detailed.
I have found this note on WordPress WP_Query reference that could be useful:
Note: Ticket #18408 For querying posts in the admin, consider using get_posts() as wp_reset_postdata() might not behave as expected.
In general, I don't use WP_Query() for customer orders but wc_get_orders() (or get_posts() too) this way:
$customer_orders = wc_get_orders( array(
'limit' => -1,
'status' => 'pending'
) );
// Iterating through each Order with pending status
foreach ( $customer_orders as $order ) {
// Going through each current customer order items
foreach($order->get_items() as $item_id => $item_values){
$product_id = $item_values['product_id']; // product ID
// Order Item meta data
$item_meta_data = wc_get_order_item_meta( $item_id );
// Some output
echo '<p>Line total for '.wc_get_order_item_meta( $item_id, '_line_total', true ).'</p><br>';
}
}
This works also just to get the orders objects.
Related documentation: wc_get_orders and WC_Order_Query
I fixed this weird issue by simply using custom query.
Somehow adding 'post_status' => 'wc-pending' doesn't actually change the query, but if I use 'post_status' => 'pending', the query changes.
So what I did was using that custom query and modify pending to wc-pending.
I do have the same issue (returning ALL Orders) while debugging.
Wrapping the debug-code into an action helped outputting the expected data:
add_action( 'init', 'debug_init' );
function debug_init() {
$custom_query_args = array(
"fields" => "ids",
"post_type" => "shop_order",
"post_status" => array('wc-processing'),
"posts_per_page" => "-1",
"offset" => "0",
"date_query" => [
"before" => "2020-09-10 23:59",
"after" => "1970-01-01 00:00",
"inclusive" => "1"
],
"order" => "DESC"
);
$debugQuery = new WP_Query( $custom_query_args );
$order_ids = $debugQuery->posts;
print_r($order_ids);
die();
}