Caveat: I'm a solo freelance designer not a developer ;-)
I've created a custom field in the Wordpress user meta called membership.
I've tried the following code to save the WooCommerce Product Name to the membership custom field on checkout with help from this answer.
Updated attempt:
function wascc_woocommerce_checkout_update_user_meta_membership ( $customer_id, $posted ) {
if (isset($posted['$orderid'])) {
$order = $posted['$orderid'];
}
$theorder = new WC_Order( $order );
$items = $theorder->get_items();
foreach ( $items as $item ) {
$product_name = $item['name'];
}
if (!(empty($product_name))) {
update_user_meta( $customer_id, 'membership', $product_name);
}
}
add_action( 'woocommerce_checkout_update_user_meta', 'wascc_woocommerce_checkout_update_user_meta_membership', 10, 2 );
It produces no error, but does not save the product name to membership.
Help appreciated.
Last question may be related.
as I've commented out, you should use woocommerce_checkout_update_order_meta.
Something like this:
function wascc_woocommerce_checkout_update_user_meta_membership ( $order_id ) {
$theorder = new WC_Order( $order_id );
$items = $theorder->get_items();
foreach ( $items as $item ) {
$product_name = $item['name'];
}
if (!(empty($product_name))) {
// Gets the customer/user ID associated with the order. Guests are 0.
$customer_id = $theorder->get_user_id();
update_user_meta( $customer_id, 'membership', $product_name );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'wascc_woocommerce_checkout_update_user_meta_membership' );
I have doubts with your foreach loop though... you are looping just to get the last item?
Related
I need to trace if a product is bought from a user coming from a specific site, that's why I need to set a meta for the order.
Let's focus on this piece of my code:
add_action( 'woocommerce_new_order', 'add_affilate_meta', 10, 1);
function add_affilate_meta( $order_id ){
$targetProd = 3115;
// check if product is present
$order = wc_get_order( $order_id );
$affiliationProduct = false;
foreach ($order->get_items() as $item_key => $item ):
$product_id = $item->get_product_id();
if($product_id == $targetProd):
$affiliationProduct = true;
break;
endif;
endforeach;
// this is just for debug
update_post_meta( $order_id, 'test_affiliate', $product_id );
... some other stuff ...
}
$affiliationProduct and, consequently, test_affiliate meta are always false/empty. Why? I'm sure, of course, that the article is present in the order. It seems like the order is not "ready" when I try to analyze it's content.
I cannot find any other way to debug the code, because I cannot var_dump() nothing without causing JSON errors.
Any help will be appreciated.
You can indeed use the woocommerce_new_order hook, but what is missing in your code is $order->save();
So you get:
function action_woocommerce_new_order( $order_id ) {
// Get the WC_Order Object
$order = wc_get_order( $order_id );
// Setting
$target_prod = 30;
// Initialize
$affiliation_product = false;
$product_id = 0;
// Loop trough
foreach ( $order->get_items() as $item_key => $item ) {
// Get
$product_id = $item->get_product_id();
// Compare
if ( $product_id == $target_prod ) {
$affiliation_product = true;
break;
}
}
// Update meta data
$order->update_meta_data( 'test_affiliate', $product_id );
// Save
$order->save();
// When true
if ( $affiliation_product ) {
// Do something
}
}
add_action( 'woocommerce_new_order', 'action_woocommerce_new_order', 10, 1 );
I have an ACF field "DeliverySpeed" attached to Products with the values 'Fast' and 'Slow'
I would like to update this field to change to value 'Slow' every time the product stock is zero or less (product on backorder)
I am still learning PHP so far this is what I got to but I am sure different things are missing, I just don't know in which direction to go:
based on acf update field documentation
function automatically_change_delivery( ) {
global $product;
$fieldkey = "DeliverySpeed";
$valueslow = "Slow";
if($product->get_stock_quantity()<0) { update_field( $field_key, $valueslow, $post_id );
} }
Thank you in advance for the attention and advice.
The following code will update automatically your product custom field once order has reduced product stock levels. So when product has stock the custom field value will be 'Fast' otherwise 'Slow'.
The code:
add_action( 'woocommerce_payment_complete', 'update_product_custom_field_after_reduced_stock_levels', 20, 2 );
add_action( 'woocommerce_order_status_completed', 'update_product_custom_field_after_reduced_stock_levels', 20, 2 );
add_action( 'woocommerce_order_status_processing', 'update_product_custom_field_after_reduced_stock_levels', 20, 2 );
add_action( 'woocommerce_order_status_on-hold', 'update_product_custom_field_after_reduced_stock_levels', 20, 2 );
function update_product_custom_field_( $order_id, $order = '' ) {
// Continue only when order has reduced product stock levels
if ( wc_string_to_bool( get_post_meta( $order_id, '_order_stock_reduced', true ) ) )
return $order_id; // Exit
if( ! $order || ! is_a( $order, 'WC_Order') ) {
$order = wc_get_order( $order_id ); // Get the WC_Order object if it's empty
}
$field_key = 'DeliverySpeed';
// Loop through order items
foreach ( $order->get_items() as $item ) {
$product = $cart_item['data'];
$product_id = $product->get_id();
$stock_qty = $product->get_stock_quantity();
$field_value = get_field( $field_key, $product_id ); // Get ACF field value
if ( $stock_qty <= 0 && $field_value === 'Fast' ) {
update_field( $field_key, 'Slow', $product_id );
}
elseif ( $stock_qty > 0 && $field_value === 'Slow' ) {
update_field( $field_key, 'Fast', $product_id );
}
}
}
Code goes in functions.php file of the active child theme (or active theme). It should works.
thank you for any of you guys wanted to help me, I just want to know how to change the user role in WordPress when users buy something. I'm using WooCommerce. Regards
You can use Woocommerce action hooks. check my below code.
add_action( 'woocommerce_thankyou', 'change_user_role_afte_buying' );
function change_user_role_afte_buying( $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
$products_to_check = array( '1', '2', '3' ); // your product ids for checking someting buy
foreach ( $items as $item ) {
if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
$user = new WP_User( $order->user_id ); // get user Object
$user->remove_role( 'customer' ); // remove old role
$user->add_role( 'new-role' ); // add new role
break; // Exit the loop
}
}
}
If an admin goes to create an order but abandons it, the stock level is still reduced.
Steps to reproduce:
install WordPress
install WooCommerce
create simple product and tick "manage stock?" and set stock level to 10
view on front-end (see screenshot before.png)
as admin create new order but don't save it (new -> order -> add item -> exit page)
view on front-end (see screenshot after.png)
Notice stock level has been reduced even those order wasn't saved.
Is there anyway to avoid this?
Before.png:
After.png
I have worked on this issue and wrote a basic code for that.
Hooks used: "woocommerce_order_item_add_action_buttons" for Admin Order Add Item(s) and "woocommerce_process_shop_order_meta" for Admin Order Creation/Update.
First part: Stop reducing stocks of items that added while the order has not been created.
// define the woocommerce_order_item_add_action_buttons callback
function action_woocommerce_order_item_add_action_buttons( $order ) {
$orderID = $order->ID;
//check if this is the admin manual order creation
if(get_post_status($orderID) == "auto-draft" && get_post_type($orderID) == "shop_order")
{
foreach( $order->get_items() as $item_id => $item )
{
$product_id = $item->get_product_id();
$variation_id = $item->get_variation_id();
$product_quantity = $item->get_quantity();
if($variation_id == 0)
{
$product = wc_get_product($product_id);
wc_update_product_stock($product, $product_quantity, 'increase');
}
else
{
$variation = wc_get_product($variation_id);
wc_update_product_stock($variation, $product_quantity, 'increase' );
}
// The text for the note
$note = __("Stock incremented due to the auto draft post type. Stock for each item will be decremented when this order created.");
// Add the note
$order->add_order_note( $note );
}
}
};
// add the action
add_action( 'woocommerce_order_item_add_action_buttons', 'action_woocommerce_order_item_add_action_buttons', 10, 1 );
Second Part: Reduce stocks of items that added if order is created.
add_action( 'woocommerce_process_shop_order_meta', 'woocommerce_process_shop_order', 10, 2 );
function woocommerce_process_shop_order ( $post_id, $post ) {
$order = wc_get_order( $post_id );
//check if this is order create action, not an update action
if(get_post_status($post_id) == "draft" && get_post_type($post_id) == "shop_order")
{
foreach( $order->get_items() as $item_id => $item )
{
$product_id = $item->get_product_id();
$variation_id = $item->get_variation_id();
$product_quantity = $item->get_quantity();
if($variation_id == 0)
{
$product = wc_get_product($product_id);
wc_update_product_stock($product, $product_quantity, 'decrease');
}
else
{
$variation = wc_get_product($variation_id);
wc_update_product_stock($variation, $product_quantity, 'decrease' );
}
// The text for the note
$note = __("Stock decremented for all items in this order.");
// Add the note
$order->add_order_note( $note );
}
}
}
Tested and works fine. I hope this will help you. Have a good day.
Right now I'm working with a mailchimp plugin that needs a custom field for validating/segmenting.
For this segment I want to check what kind of coupon is used. So I scavenged the following code that should fill my custom field with the used coupons:
add_action( 'woocommerce_checkout_update_order_meta',
'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( empty( $_POST['my_field_name'] ) ) {
$coupons = $order->get_used_coupons();
update_post_meta( $order_id, 'my_field_name', $coupons);
}
}
Sadly this will only crash my site.
Any help would be greatly appreciated.
There are several problems with your code:
You're not validating if the field has any information, so you need
to check if $_POST has the my_field_name key
You need to load the $order variable in order to get the used coupons.
What happens when there's a my_field_value? Do you store it?
Here's the modified code:
add_action( 'woocommerce_checkout_update_order_meta',
'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order_id, $posted ) {
if ( isset($_POST['my_field_name']) && empty( $_POST['my_field_name'])) {
$order = new WC_Order( $order_id );
$coupons = $order->get_used_coupons();
update_post_meta( $order_id, 'my_field_name', $coupons);
}
}