WooCommerce codex : how to set the user/customer on an order - php

I am writing a WooCommerce Plugin that takes care of payment and delivery.
Right now I am at the point of creating an order based on the current shopping cart.
That all works fine getting the items and costs correct, the only problem is that the order shows as being made by "Guest", instead of by the currently logged on user (even though the correct email address for that user is on the order).
Here is my code :
$cart = WC()->cart;
$checkout = WC()->checkout();
$order_id = $checkout->create_order();
$order = wc_get_order( $order_id );
$order->user_id = apply_filters( 'woocommerce_checkout_customer_id', get_current_user_id() );
$order->calculate_totals();
$order->payment_complete();
$cart->empty_cart();
Here is what I see in the backend after running this :
Why is the order placed as "Guest" instead of the user that placed the order?
And how do I get to have the correct user attached?

You will need to add _customer_user to post_meta table with order ID and meta value should be the user ID which you want to link to this order.
I hope that this will help you:
update_post_meta($order_id, '_customer_user', get_current_user_id());

OR
use user/customer id(create a customer/user before place order) in wc_create_order();
eg: $order = wc_create_order(array('customer_id' => $user));
this code fine for me!

Related

How to get the order information inside the customer creation hook?

When a visitor buys a new product in my WooCommerce shop, I'm using the woocommerce_created_customer hook to create a new user on an external database with some information I get from the $customer_id, $new_customer_data, $password_generated arguments.
For example:
function action_woocommerce_created_customer($customer_id, $new_customer_data, $password_generated) {
// Create a new user on external database
}
add_action('woocommerce_created_customer', 'action_woocommerce_created_customer', 10, 3);
Well. What I need is a connection to the current order to get the order id. In my shop, a user account can only be created in combination with an order. Is there a way to get order information inside the woocommerce_created_customer hook? Or is this do_action just called before the order is done?
I thought about using another hook after the payment is done. But this is not possible in my case because this is the only hook I found which I can get the unhashed user password, which I very need.
Do you have an idea how to get the order information inside the customer creation hook?
The order is created after the customer.
$this->process_customer( $posted_data );
$order_id = $this->create_order( $posted_data );
$order = wc_get_order( $order_id );
Use this hook to do the stuff.
do_action( 'woocommerce_checkout_order_processed', $order_id, $posted_data, $order );
$posted_data contains the username and password
$username = ! empty( $posted_data['account_username'] ) ? $posted_data['account_username'] : '';
$password = ! empty( $posted_data['account_password'] ) ? $posted_data['account_password'] : '';

Changing Woocommerce Order Status based on order notes

I've been looking around to find a way to change our woocommerce orders status based on the order notes. We have a card processor that adds order notes when an order is approved, but it puts the order on hold because the card is only authorized not charged. We charge the card later once the order has been shipped, but we need the order to go into "processing" so we can export the order into our system so we can actually process the order (we don't process through woocommerce).
I found this code however, I'm wondering if this can be modified to pull what is in the order notes since our processor adds whether or not the card has been approved.
function mysite_woocommerce_payment_complete( $order_id ) {
error_log( "Payment has been received for order $order_id" );
}
add_action( 'woocommerce_payment_complete', 'mysite_woocommerce_payment_complete', 10, 1 );
Here is a Example which switch on hold order status with processing. you can use it or if need to add some more condition, please mention here or update it accordingly. Thanks
function switch_hold_status_to_processing ($order_id) {
$order = new WC_Order( $order_id );
$order->update_status('processing');
}
add_action('woocommerce_order_status_on-hold', 'switch_hold_status_to_processing');
You can use wc_get_order_notes($args) function to get the order notes in the specific order. It returns an array of order notes. Then you can loop through the array to find the order note you need. Then use an if statement to verify the content of the order note and update the status.
function mysite_woocommerce_payment_complete( $order_id ) {
$order_notes = wc_get_order_notes([
'order_id' => $order_id,
]);
foreach ($order_notes as $order_note){
if ($order_note->content == "Order verified"){
$order = new WC_Order( $order_id );
$order->update_status('processing');
break;
}
}
}
add_action( 'woocommerce_payment_complete', 'mysite_woocommerce_payment_complete', 10, 1 );

Woocommerce update stock by ID after payment

I created a custom product type for WooCommerce. With this product type it is possible to connect an other product that is exist by ID.
WooCommerce reduce the stock quantity automatically if an order is placed and the payment is successful.
For example I added a product with ID 4082 to the cart with a quantity from 3.
After place this order WooCommerce updated the stock from product 4082 with -3.
Ok back to my custom product type. As I said it is possible to connect another product by ID.
For example I connect product 4082 with product ID 10988.
If a customer add product 4082 to the cart and placed the order I want reduce the stock quantity from product ID 10988 and not from 4082.
<?php
add_action('woocommerce_checkout_order_processed', 'stocktest');
function stocktest($order_id){
$order = wc_get_order( $order_id );
$order_item = $order->get_items();
foreach( $order_item as $product ) {
//for the topic I programmed the IDs hardcoded
if($product->ID == '4082'){
wc_update_product_stock( 10998, $product['qty'], 'decrease', '' );
}
}
}
?>
I tried the code above and the stock from ID 10998 is correctly decreased but also the stock from ID 4082 is decreased.
Do I use the wrong hook? And how can I make the function correctly?
Hope somebody can help me with this.
Thanks a lot
Does wc_update_product_stock( 4082, $product['qty'], 'increase', '' ); not work?
That way, the stock should be adjusted for the 4082 product.
Also, there might be a potential issue with your snippet. The $product variable refers to the product object of 4082 product, not the 10998 product.
Maybe try something like this?
<?php
add_action('woocommerce_checkout_order_processed', 'stocktest');
function stocktest($order_id){
$order = wc_get_order( $order_id );
$order_item = $order->get_items();
foreach( $order_item as $product ) {
//for the topic I programmed the IDs hardcoded
if($product->ID == '4082'){
$connected_qty = get_post_meta( 10988, '_stock', true );
wc_update_product_stock( 10998, $connected_qty, 'decrease', '' );
wc_update_product_stock( 4082, $product['qty'], 'increase', '' );
}
}
}
?>
Instead of using the custom field query, you could use the WC_Product class:
$connected_product = wc_get_product(10998);
$connected_qty = $connected_product->get_stock_quantity();
I did some research on your question. WooCommerce called a lot of functions to update the stock af order / payment. If an order is placed the items become an status reduce_stock yes or no.
If is yes go further and update the stock of this item. After this WooCommerce created the e-mails and ordernotes.
All this functions worked together please be careful with changing the code in the file wc-stock-functions.php
If you want change and try something do this for example on a local testserver.
This are some functions in the file
<?php
wc_maybe_reduce_stock_levels();
wc_maybe_increase_stock_levels();
wc_reduce_stock_levels();
wc_trigger_stock_change_notifications();
?>

Woocommerce: change order id after payment is completed

I have made a simple webshop with woocommerce, with three payment methods. iDeal and by direct bank transfer and on account. The order ID is created based on the payment method. for example, if payment is made with iDEAL, the order id becomes ID190100; if payment is made on account, the order id becomes RK190100. I get this working with the plugin
"Sequential Order Numbers for WooCommerce" from BeRocket but these are already created before the payment is complete. The order ID must only be finalized once the payment has been made. Now orders that have not yet paid, and may not be paying, will receive a fixed order ID. So is it possible to create a temporary order id and when the order is completed change the order id based on payment method?
Woocommerce by default will use the post ID of the order for the order ID. This is evident when viewing the WC_Order::get_order_number() method. If you want to use a custom order number to display, you'll need to add a filter on woocommerce_order_number to load in a different value.
An example script would be:
add_action( 'woocommerce_order_status_completed', 'wc_change_order_id' );
function wc_change_order_id( $order_id ) {
$order = wc_get_order( $order_id );
$method = $order->get_payment_method(); // need check this
if ( $method === 'account' ) {
$number = 'ID' . $order->get_id();
$order->update_meta_data('_new_order_number', $number );
}
}
add_filter('woocommerce_order_number', function($default_order_number, \WC_Order $order) {
//Load in our meta value. Return it, if it's not empty.
$order_number = $order->get_meta('_new_order_number');
if(!empty($order_number)) {
return $order_number;
}
// use whatever the previous value was, if a plugin modified it already.
return $default_order_number;
},10,2);
Try this. It's very quick example. Hope help.
add_action( 'woocommerce_order_status_completed', 'wc_change_order_id' );
function wc_change_order_id( $order_id ) {
$order = wc_get_order( $order_id );
$method = $order->get_payment_method(); // need check this
if ( $method === 'account' ) {
$number = 'ID' . $order->get_id();
$order->set_id( $number );
$order->save();
}
}

Function to pull product URL from Order details page in woocommerce

I am using woocommerce bookings plugin and I am looking for a solution for customers who have already booked a time slot to be able to add more time to their booking. In theory, it would be great if they could just edit their booking and pay the difference but from what I can tell that would require an extensive amount of custom code which I am not capable of doing. So as an alternative solution, perhaps I can create a unique button on the customer's order detail page at /my-account/booking-details/OrderID/ where they can go to a specific product based on the product of that order.
I have created a custom hook on the /order-details.php file called woocommerce_extra_time_button and added the below code to my theme's function.php file but I am not able to pull the product URL as I thought I would.
add_action( 'woocommerce_extra_time_button', 'booking_extratime_button', 10, 3 );
function booking_extratime_button( $item_id, $item ){
$url = get_permalink( $item['product_id'] ) ;
return ''. $item_id .'';
}
You can find the product detail from the order of current user and use inside your custom hook. for example :
$order = wc_get_order( $order_id );
$items = $order->get_items()
foreach ( $items as $item ) {
$product_name = $item->get_name();
$product_id = $item->get_product_id();
$product_variation_id = $item->get_variation_id();
}

Categories