I am trying to update a product meta for all products of each order that gets completed. Can you have a look at my approach below? Any help on why it is not working will be appreciated. I am new to all this php customizing.
add_action( 'woocommerce_order_status_completed', 'update_product_meta', 20, 2 );
function update_product_meta ( $order_id, $order ) {
// GET USER ORDERS (COMPLETED + PROCESSING)
$args = array(
'post_status' => array('wc-completed')
);
$done_orders = wc_get_orders( $args );
// LOOP THROUGH ORDERS AND GET PRODUCT IDS
if ( $done_orders ) {
$product_ids = array();
foreach ( $done_orders as $done_order ) {
$order = wc_get_order( $done_order->ID );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
}
}
add_action( 'woocommerce_process_product_meta', 'action_save_product_meta' );
function action_save_product_meta( $product_id ) {
update_post_meta($product_id, 'Stav', 'Vypůjčeno' );
}
}
}
Well you're pretty close, you just have to remove the nonsense at the end.
Something along the lines of:
<?php
add_action( 'woocommerce_order_status_completed', function ( $order_id, $order ) {
$args = array(
'post_status' => array('wc-completed')
);
$done_orders = wc_get_orders( $args );
if ( ! empty( $done_orders ) ) {
foreach ( $done_orders as $done_order ) {
$order = wc_get_order( $done_order->ID );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
update_post_meta( $product_id, 'Stav', 'Vypůjčeno' );
};
};
};
}, 20, 2 );
You should think of limiting it to a specific amount because right now your query will request ALL items ever completed. be careful.
Related
I wanted to know how to automatically delete an order when a user ordering a Specific product/category if it was in pending in 5m.
I have this code but when I add it to my function.php it doesn't work.
function update_order_status( $order_id ) {
$order = new WC_Order( $order_id );
$order_status = $order->get_status();
if ('pending' == $order_status ) {
$current_time = date('h:i:s');
sleep(600);
wp_delete_post($order_id,true);
}
}
You can use the CRON job and then get all orders with pending status and then check their order date with the current date and delete.
Add custom 5-minute cron schedules by using WC cron_schedules hook
function add_five_minute_cron_schedules($schedules){
if( !isset( $schedules["five_minute"] ) ){
$schedules["five_minute"] = array(
'interval' => 5*60,
'display' => __('Once every 5 minutes')
);
}
return $schedules;
}
add_filter('cron_schedules','add_five_minute_cron_schedules');
Scheduled your CRON on WP init Hook.
if( ! wp_next_scheduled( 'remove_pending_order_after_five_minute' ) ){
wp_schedule_event( time(), 'five_minute', 'remove_pending_order_after_five_minute' );
}
//Hook into that action that'll fire every 5 minutes.
add_action( 'remove_pending_order_after_five_minute', 'remove_pending_order_after_five_minute_callback' );
function remove_pending_order_after_five_minute_callback(){
// get all pending orders that created in the last 5 minutes.
$args = array(
'post_status' => array( 'wc-processing', 'wc-pending', 'wc-on-hold' ),
'date_created' => '<' . ( time() - 300 ),
'posts_per_page' => -1
);
$orders = wc_get_orders($args);
if( !empty( $orders ) ){
// Loop through each $order objects.
foreach( $orders as $order ){
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
$order = wc_get_order( $order_id );
if ( $order && sizeof( $order->get_items() ) > 0 ) {
foreach( $order->get_items() as $item ) {
if( has_term( 'charkh', 'product_cat', $item->get_product_id() ) ) {
wp_delete_post( $order_id );
break;
}
}
}
}
}
}
This code goes to active theme functions.php file. Tested and works.
I have two scripts that are interfering with each other. What I need for this website is that: all successful purchases should go to page https://aefcoaching.com/gracias-por-tu-compra, except successful purchase of Product ID 1813, which should go to https://aefcoaching.com/gracias-gimnasio-mental/
/* # Redirect to the Thank You page after successful payment in WooCommerce */
if( !function_exists('sc_custom_redirect_after_purchase') ):
function sc_custom_redirect_after_purchase() {
global $wp;
if ( is_checkout() && !empty($wp->query_vars['order-received']) ) :
$order_id = absint($wp->query_vars['order-received']);
$order_key = wc_clean($_GET['key']);
$th_page_url = 'https://aefcoaching.com/gracias-por-tu-compra';
$redirect = add_query_arg(
array(
'order' => $order_id,
'key' => $order_key,
), $th_page_url);
wp_safe_redirect($redirect);
exit;
endif;
}
add_action('template_redirect', 'sc_custom_redirect_after_purchase');
endif;
/* # Redirect Gimnasio Mental purchases to a specific Thank You Page */
function action_woocommerce_thankyou( $order_id ) {
if( ! $order_id ) {
return;
}
// Instannce of the WC_Order Object
$order = wc_get_order( $order_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// False
$redirection = false;
// Loop through order items
foreach ( $order->get_items() as $item_key => $item ) {
// Product ID(s)
$product_ids = array( $item->get_product_id(), $item->get_variation_id() );
// Product ID in array
if ( in_array( 1813, $product_ids ) ) {
$redirection = true;
}
}
}
// Make the custom redirection when a targeted product has been found in the order
if ( $redirection ) {
wp_safe_redirect( home_url( '/gracias-gimnasio-mental/' ) );
exit;
}
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
The first piece works great. The second doesn't because of the first one. I'm not sure how to integrate these two rather than have 2 separate codes. Can you help me?
Please merge the two logics into one , by changing your sc_custom_redirect_after_purchase function into the following:
function sc_custom_redirect_after_purchase() {
global $wp;
if ( is_checkout() && !empty($wp->query_vars['order-received']) ) :
$order_id = absint($wp->query_vars['order-received']);
$order_key = wc_clean($_GET['key']);
$th_page_url = 'https://aefcoaching.com/gracias-por-tu-compra';
//////////////////////
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $item_key => $item ) {
// Product ID(s)
$product_ids = array( $item->get_product_id(), $item->get_variation_id() );
// Product ID in array
if ( in_array( 1813, $product_ids ) ) {
// $redirection = true;
$th_page_url = 'https://aefcoaching.com/gracias-gimnasio-mental/';
}
}
/////////////////////
$redirect = add_query_arg(
array(
'order' => $order_id,
'key' => $order_key,
), $th_page_url);
wp_safe_redirect($redirect);
exit;
endif;
}
One of my products requires a specific thank you page.
Here's the code I have. The Product ID is 1813 and the category is gimnasio-mental. I don't really need, nor want to include the category in this code, so if it can be simplified, even better!
add_action( 'template_redirect', 'wc_custom_redirect_after_purchase' );
function wc_custom_redirect_after_purchase() {
if ( ! is_wc_endpoint_url( 'order-received' ) ) return;
// Define the product IDs in this array
$product_ids = array( 1813 ); // or an empty array if not used
// Define the product categories (can be IDs, slugs or names)
$product_categories = array( 'gimnasio-mental' ); // or an empty array if not used
$redirection = false;
global $wp;
$order_id = intval( str_replace( 'checkout/order-received/', '', $wp->request ) ); // Order ID
$order = wc_get_order( $order_id ); // Get an instance of the WC_Order Object
// Iterating through order items and finding targeted products
foreach( $order->get_items() as $item ){
if( in_array( $item->get_product_id(), $product_ids ) || has_term( $product_categories, 'product_cat', $item->get_product_id() ) ) {
$redirection = true;
break;
}
}
// Make the custom redirection when a targeted product has been found in the order
if( $redirection ){
wp_redirect( home_url( '/gracias-gimnasio-mental/' ) );
exit;
}
}
You could use the woocommerce_thankyou action hook against template_redirect
Explanation via comment tags added in the code
function action_woocommerce_thankyou( $order_id ) {
if( ! $order_id ) {
return;
}
// Instannce of the WC_Order Object
$order = wc_get_order( $order_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// False
$redirection = false;
// Loop through order items
foreach ( $order->get_items() as $item_key => $item ) {
// Product ID(s)
$product_ids = array( $item->get_product_id(), $item->get_variation_id() );
// Product ID in array
if ( in_array( 1813, $product_ids ) ) {
$redirection = true;
}
}
}
// Make the custom redirection when a targeted product has been found in the order
if ( $redirection ) {
wp_safe_redirect( home_url( '/gracias-gimnasio-mental/' ) );
exit;
}
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
I want to display the order table found in woocommerce my-account recent orders for a specific product id on a separate page. To be more precise, display all recent orders for current user if the order has a product with the product_id of X.
I am trying to use these references:
Woocommerce - How to show Order details (my-account) on a separate page
Get all Orders IDs from a product ID in Woocommerce
Woocommerce: Get all orders for a product
But I am not able to relate $product_id to $user_id = get_current_user_id(); so that all the orders of the current user for a particular product id can be displayed on a separate page.
Edit: added code. I tried this code but its not working.
function orders_from_product_id( $product_id ) {
$order_statuses = array('wc-on-hold', 'wc-processing', 'wc-completed');
$customer_user_id = get_current_user_id(); // current user ID here for example
$customer_orders = wc_get_orders( array(
'meta_key' => '_customer_user',
'meta_value' => $customer_user_id,
'post_status' => $order_statuses,
'numberposts' => -1
) );
foreach($customer_orders as $order ){
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
foreach($order->get_items() as $item_id => $item){
$product_id = method_exists( $item, 'get_product_id' ) ? $item->get_product_id() : $item['product_id'];
if ( $product_id == 326 ) {
ob_start();
wc_get_template( 'myaccount/my-orders.php', array(
'current_user' => get_user_by( 'id', $user_id),
'order_count' => $order_count
) );
return ob_get_clean();
} else {
echo '<p> You donot have any orders.</p>';
}
}
}
}
add_shortcode('woocommerce_orders', 'orders_from_product_id');
From this code you to get the Current user-product id which product purchased by the user.
// GET CURR USER
$current_user = wp_get_current_user();
if ( 0 == $current_user->ID ) return;
// GET USER ORDERS (COMPLETED + PROCESSING)
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $current_user->ID,
'post_type' => wc_get_order_types(),
'post_status' => array_keys( wc_get_is_paid_statuses() ),
) );
// LOOP THROUGH ORDERS AND GET PRODUCT IDS
if ( ! $customer_orders ) return;
$product_ids = array();
foreach ( $customer_orders as $customer_order ) {
$order = wc_get_order( $customer_order->ID );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
$product_ids[] = $product_id;
}
}
$product_ids = array_unique( $product_ids );
I have a problem with php realization of automaticaly changing role of user.
So i have custom role dovclient. First time user ordering get role Customer.
I need to change user role if he has buy products total 500$.
So i have a function
function wpa_120656_convert_paying_customer( $order_id ) {
$order = new WC_Order( $order_id );
$user_id = $order->user_id;
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_order',
) );
$total = 0;
foreach ( $customer_orders as $customer_order ) {
$order = wc_get_order( $customer_order );
$total += $order->get_total();
}
return $total;
if ( $total > 500 ) {
update_user_meta( $order->user_id, 'paying_customer', 1 );
$user = new WP_User( $order->user_id );
$user->remove_role( 'customer' );
$user->add_role( 'dovclient10' );
}
}
add_action( 'woocommerce_order_status_completed', 'wpa_120656_convert_paying_customer' );
I know, that $customer_orders are counting, and i make function working by count of orders. I mean if $customer_orders > 2 for ex., so change role.
But with total of order prices i have a problem. Role changes not. I don't know why. Maybe problem is in foreach...
Please help me!
Amazing help! 0... ok. I have done it.
function wpa_120656_convert_paying_customer( $order_id ) {
$order = new WC_Order( $order_id );
$user_id = $order->user_id;
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_order',
) );
$totall = 0;
foreach ( $customer_orders as $customer_order ) {
$order = wc_get_order( $customer_order );
$totall += $order->get_total();
}
if ( $totall > 500 ) {
update_user_meta( $order->user_id, 'paying_customer', 1 );
$user = new WP_User( $order->user_id );
if( get_role('customer') ){
$user->remove_role( 'customer' );
$user->add_role( 'dovclient' );
}
}
}
add_action( 'woocommerce_order_status_completed', 'wpa_120656_convert_paying_customer' );