Is there woocommerce function that will return me all related orders (at least the order ID) for the specific subscription that user has bough?
I have found in this official documentation Subscription Function & Property Reference:
WC_Subscription::get_related_orders( $return_fields, $order_type );
But this does not seem to be for specific subscription?
When ever I try to run it I get a fatal error no mater what I pass in:
Fatal error: Uncaught Error: Using $this when not in object context in
C:\xampp\htdocs\mysite.com\wp-content\plugins\woocommerce-subscriptions\includes\class-wc-subscription.php:1413
I am making my own plugin and I select all subscriptions where post status = wc-active from post table. I have looked in the "woocommerce_order_items", "woocommerce_order_itemmeta" and "postmeta" tables but neither of them provide way to get related orders for user bought subscription...
If I only knew where are the relation for user bought subscriptions and its related orders, then i could write some sql but I have no idea and google does not yield any results either.
Any ideas?
My setup:
php version 7.0.4
wordpress version 4.7.3
woocommerce 2.6.8
woocommerce subscriptions: 2.0.18
Updated: Added WooCommerce version 3+ Compatibility
It's very easy to get the order ID from subscription object. I am going to select, just like you, all subscriptions where 'post status' = 'wc-active' from post table.
// Get all customers subscriptions
$customer_subscriptions = get_posts( array(
'numberposts' => -1,
// 'meta_key' => '_customer_user',
// 'meta_value' => get_current_user_id(), // Or $user_id
'post_type' => 'shop_subscription', // WC orders post type
'post_status' => 'wc-active' // Only orders with status "completed"
) );
// Iterating through each post subscription object
foreach( $customer_subscriptions as $customer_subscription ){
// The subscription ID
$subscription_id = $customer_subscription->ID
// IMPORTANT HERE: Get an instance of the WC_Subscription Object
$subscription = new WC_Subscription( $subscription_id );
// Or also you can use
// wc_get_order( $subscription_id );
// Getting the related Order ID (added WC 3+ comaptibility)
$order_id = method_exists( $subscription, 'get_parent_id' ) ? $subscription->get_parent_id() : $subscription->order->id;
// Getting an instance of the related WC_Order Object (added WC 3+ comaptibility)
$order = method_exists( $subscription, 'get_parent' ) ? $subscription->get_parent() : $subscription->order;
// Optional (uncomment below): Displaying the WC_Subscription object raw data
// echo '<pre>';print_r($subscription);echo '</pre>';
}
You can also uncomment in the post query the 'meta_key' and 'meta_value' array lines to get the subscriptions for one customer… This code is tested and works
The most important thing here is:
$subscription = new WC_Subscription($customer_subscription->ID);
…as you will get the WC_Subscription object in which you can apply all WC_Subscription methods without getting errors, with for example:
$subscription = new WC_Subscription($post_id);
$relared_orders_ids_array = $subscription->get_related_orders();
Related
We had a legacy system that used Woocommerce but not Woocommerce Subscriptions, we've since migrated to Woocommerce Subscriptions but we have a tonne of standard Woo orders that we'd like to tie to subscriptions.
Via the database, if I find the subscription in the postmeta table, I can manually change _subscription_renewal_order_ids_cache to include the order id so it becomes the following:
a:2:{
i:0;i:143052;
i:1;i:143049;
}
(I've added the second line)
On the order itself if I add the meta _subscription_renewal with the subscription id that then ties the order to the subscription.
Can this be done programmatically? I've done the following but it's not outputting the meta (so therefore I can't amend it).
global $wpdb;
// get all subscriptions IDS
$subscriptions_ids = $wpdb->get_col("
SELECT ID FROM {$wpdb->prefix}posts
WHERE post_type LIKE 'shop_subscription'
");
// Loop through subscriptions Ids
foreach( $subscriptions_ids as $subscription ){
// Get an instance of the WC_Subscription object
$subscription = new WC_Subscription( $subscription );
$subscription_id = $subscription->get_id();
$subscription_email = $subscription->get_billing_email();
echo $subscription->get_meta('_subscription_renewal_order_ids_cache');
echo "<pre>";
print_r( $subscription );
echo "</pre>";
}
I've not gone any further with the code until I'm able to output and amend the post meta.
This can be done by going through orders and adding the meta line:
$order = wc_get_order();
$order->update_meta_data( '_subscription_renewal', $subscription_id );
$order->save();
With $subscription_id being the ID of the subscription you'd like to tie the order to.
I'm trying to get the subscription id from the action hook woocommerce_order_status_changed.
It gives me the order id which is changed with every switch the customer makes.
For example: If the subscription id is 10, the original order id is 9.
Now every switch the customer made generates a new order id, which the action above gives you. At this point I have the $customer_id, $order_id, and the original post id which is 9,
How I can get the subscription id of the current order?
You can use dedicated function wcs_get_subscriptions_for_order() which will retrieve $subscription IDs.
So this could be your code:
add_action('woocommerce_order_status_changed', 'action_order_status_changed');
function action_order_status_changed( $order_id ){
$subscriptions_ids = wcs_get_subscriptions_for_order( $order_id, array( 'order_type' => 'any' ) );
// We get all related subscriptions for this order
foreach( $subscriptions_ids as $subscription_id => $subscription_obj )
if($subscription_obj->order->id == $order_id) break; // Stop the loop
// The subscription ID: $subscription_id
// The An instance of the Subscription object: $subscription_obj
// ...
}
I'm using woocommerce subscriptions and I'm writing a plugin to update an external system, if the user upgrade or downgrade his subscription it shows as a new order with its ID, but I can't get the subscription ID (which it's constant) related to the order ID, I check the documentation but I couldn't find a solution.
I was able to achieve like this.
$subscriptions = wcs_get_subscriptions_for_order($order_id, array( 'order_type' => 'any' ));
foreach( $subscriptions as $subscription_id => $subscription_obj )
{
$current_subs_id = $subscription_obj->get_id(); // This is current subscription id
$parent_id = $subscription_obj->get_parent_id(); // This is subscription parent id
}
You can access this data by hooking into the processed_subscription_payment action provided by WooCommerce Subscriptions:
add_action( 'processed_subscription_payment', 'se43079522_process_subscription', 10, 2 );
function se43079522_process_subscription($user_id, $subscription_key) {
// here you have access to the $subscription_key (ID) and the $user_id associated
}
Take a look at this link: https://docs.woocommerce.com/document/subscriptions/develop/action-reference/ for more information on the available actions with this plugin.
OR, you can do this manually like so:
Read comments for walk-through
global $woocommerce;
// Get the order ID and save as variable
$order_id = [ORDER_ID];
// Get the order object
$order = new WC_Order( $order_id );
// Loop through the subscription order
foreach ( WC_Subscriptions_Order::get_recurring_items( $order ) as $order_item ) {
// Get the subscription key
$subscription_key = WC_Subscriptions_Manager::get_subscription_key( $order->id, WC_Subscriptions_Order::get_items_product_id( $order_item ) );
}
// This is your subscription key (ID)
echo $subscription_key;
Get Subscription ID from Order. You can use wcs_get_subscriptions_for_order woocommerce function to get an object with the subscription related to that order and get the subscription ID from there.
$subscriptions = wcs_get_subscriptions_for_order($order_id);
var_dump($subscriptions);
I own/operate a WooCommerce Shop and I am looking for a way to Set up a Shop Notice when More than One Order comes in from the same Customer, Shipping to the Same Address.
I have been lucky enough to be blessed with tons of repeat customers. They will order from my shop on let's say a Monday and pay the shipping rate for their item(s) & then order on say a Tuesday (before I am able to ship out the first order), so I try to include the second product into first order to "SAVE" on shipping. But I can only save on Shipping if I pay attention to the customer's shipping address and bundle the items.
I would like my site to be a bit more efficient in this area and check for "OPEN" or "PROCESSING" orders that have matching shipping address's and pop up an alert when I open one of the orders in question...
Is something like this possible?
I have searched and searched and searched and nothing... I'm not completely sure where to start on this...
Is this possible with a custom script in functions.php file?
Is there a plugin that can help do this?
Any help is greatly appreciated.
Thanks.
Version code for WooCommerce 3+
add_action( 'woocommerce_admin_order_data_after_order_details', 'same_shipping_open_order', 10, 1 );
function same_shipping_open_order( $order ){
// Define HERE, in the array, your "OPEN" orders statuses
$open_order_statuses = array('wc-pending','wc-processing','wc-on-hold');
// Initialising variables
$matching = false;
// Get Order data (WC 3+ compatibility)
$order_data = $order->get_data();
// Get the shipping 'address_1' & 'postcode' fields for the CURRENT ORDER
$order_ship_address1 = $order_data['shipping']['address_1']; # (WC 3+ compatibility)
$order_ship_postcode = $order_data['shipping']['postcode']; # (WC 3+ compatibility)
// Getting customer orders, with an open status
$open_orders = wc_get_orders( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $order->get_user_id(),
'post_type' => 'shop_order',
'post_status' => $open_order_statuses,
'exclude' => array($order_data['id']), # (WC 3+ compatibility)
) );
// Other "Open" orders for this customer
if( count($open_orders) != 0 ){
// Iterating through each orders
foreach($open_orders as $open_order){
// Get "open" Order data (WC 3+ compatibility)
$open_order_data = $open_order->get_data();
// Orders Id
$open_order_id = $open_order_data['id'];
if( $order_ship_address1 == $open_order_data['shipping']['address_1'] && $order_ship_postcode == $open_order_data['shipping']['postcode'] ){
// set condition to true (There is at once 1 matched order)
$matching = true;
// Other orders edit url
$order_edit_url = home_url( "/wp-admin/post.php?post=$open_order_id&action=edit/" );
// Storing orders edit url + ID
$results_arr[] = "<a href='$order_edit_url'>#$open_order_id</a>";
}
}
}
// If there is matching "Open" orders shipping addresss with this order
if ( $matching ) {
## 0. Converting the array in a string for output
$output_html = implode(', ', $results_arr);
## 1. Displaying an alert message on the order
echo '<br clear="all"><p style="margin-top:12px !important;"><strong style="color:red;">'. __("Same Shipping on Open Orders IDs: ").'</strong><br>'.$output_html.'</p>';
## 2. Javascript Alert message
?>
<script>
(function($){
alert('SAME SHIPPING ON OPEN ORDERS!');
})(jQuery);
</script>
<?php
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works the same way on WooCommerce 3+
See this related updated answer: How to get order details
in WooCommerce 3.0+
For WooCommerce version 2.5.x and 2.6.x
For WOOCOMMERCE VERSION 3.0+ see THIS UPDATE
This is completely possible using in woocommerce_admin_order_data_after_order_details action hook a custom hooked function in which you will have to define in an array the orders statuses for your "Open orders".
Here is this functional and tested code:
add_action( 'woocommerce_admin_order_data_after_order_details', 'same_shipping_open_order', 10, 1 );
function same_shipping_open_order( $order ){
// Define HERE, in the array, your "OPEN" orders statuses
$open_order_statuses = array('wc-pending','wc-processing','wc-on-hold');
// Initialising variables
$matching = false;
// Get the shipping 'address_1' & 'postcode' fields for the CURRENT ORDER
$order_ship_address1 = $order->shipping_address_1;
$order_ship_postcode = $order->shipping_postcode;
// Getting customer orders, with an open status
$open_orders = wc_get_orders( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $order->get_user_id(),
'post_type' => 'shop_order',
'post_status' => $open_order_statuses,
'exclude' => array($order->id),
) );
// Other "Open" orders for this customer
if( count($open_orders) != 0 ){
// Iterating through each orders
foreach($open_orders as $open_order){
if( $order_ship_address1 == $open_order->shipping_address_1 && $order_ship_postcode == $open_order->shipping_postcode ){
$matching = true; // set condition to true
$open_order_id = $open_order->id;
// Other orders edit url
$order_edit_url = home_url( "/wp-admin/post.php?post=$open_order_id&action=edit/" );
// Storing orders edit url + ID
$results_arr[] = "<a href='$order_edit_url'>#$open_order_id</a>";
}
}
}
// If there is matching "Open" orders shipping addresss with this order
if ( $matching ) {
## 0. Converting the array in a string for output
$output_html = implode(', ', $results_arr);
## 1. Displaying an alert message on the order
echo '<br clear="all"><p style="margin-top:12px !important;"><strong style="color:red;">'. __("Same Shipping on Open Orders IDs: ").'</strong><br>'.$output_html.'</p>';
## 2. Javascript Alert message
?>
<script>
(function($){
alert('SAME SHIPPING ON OPEN ORDERS!');
})(jQuery);
</script>
<?php
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
You will get an alert message when opening/editing the order and also a text with the related "Open orders Ids and edit links. See the screenshot below:
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Here is the situation. I have a woocommerce site used as a marketplace. I'm selling games on it, for some the purchaser receive a steam key. For that I'm working on a key attribution system, so by going on a page, the key will be attributes to the user.
For that, I want to check all orders made by the current user (the on log-in and on the page) and check the game he has bought.
I find some very usefull information here: How to get WooCommerce order details
However, I don't manage to get all orders the current user. I have first think to make a SQL request, but I don't find the link on the database between order and user.
Have you any lead?
Updated Added Compatibility with WooCommerce 3+ (January 2018)
Here is the code that you will need to get all customer orders and to go through each items of each customer order:
## ==> Define HERE the statuses of that orders
$order_statuses = array('wc-on-hold', 'wc-processing', 'wc-completed');
## ==> Define HERE the customer ID
$customer_user_id = get_current_user_id(); // current user ID here for example
// Getting current customer orders
$customer_orders = wc_get_orders( array(
'meta_key' => '_customer_user',
'meta_value' => $customer_user_id,
'post_status' => $order_statuses,
'numberposts' => -1
) );
// Loop through each customer WC_Order objects
foreach($customer_orders as $order ){
// Order ID (added WooCommerce 3+ compatibility)
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
// Iterating through current orders items
foreach($order->get_items() as $item_id => $item){
// The corresponding product ID (Added Compatibility with WC 3+)
$product_id = method_exists( $item, 'get_product_id' ) ? $item->get_product_id() : $item['product_id'];
// Order Item data (unprotected on Woocommerce 3)
if( method_exists( $item, 'get_data' ) ) {
$item_data = $item->get_data();
$subtotal = $item_data['subtotal'];
} else {
$subtotal = wc_get_order_item_meta( $item_id, '_line_subtotal', true );
}
// TEST: Some output
echo '<p>Subtotal: '.$subtotal.'</p><br>';
// Get a specific meta data
$item_color = method_exists( $item, 'get_meta' ) ? $item->get_meta('pa_color') : wc_get_order_item_meta( $item_id, 'pa_color', true );
// TEST: Some output
echo '<p>Color: '.$item_color.'</p><br>';
}
}
This code is tested and works
Related:
How to get WooCommerce order details
Accessing Order Items protected data in Woocommerce 3
Get Order items and WC_Order_Item_Product in WooCommerce 3