This question already has answers here:
How to get WooCommerce order details
(6 answers)
Get Order items and WC_Order_Item_Product in WooCommerce 3
(2 answers)
Closed 3 years ago.
I'm trying to access users purchase information from my wordpress admin plugin so that I can summarise orders e.g:
Product name
Custom data (in my case text associated with the
product)
When it was bought
How much they paid
It's mostly the information you can find on the "Account" > "Orders" page when the user is logged in.
I've looked through the woocommerce tables but can't find this information.
Can you suggest which tables I can query to pull together the information I'm looking for above?
The orders are stored at the wp_posts table with a 'shop_order' custom post type.
You can simply use the woocommerce function like this.
$woo_orders = wc_get_orders( array('numberposts' => -1) );
/* Loop each WC_Order object */
foreach( $woo_orders $order ){
/* Get the ID */
echo $order->get_id();
/* Get the status */
echo $order->get_status(); // The status
}
Or use the normal wordpress loop:
$loop = new WP_Query( array(
'post_type' => 'shop_order',
'posts_per_page' => -1,
'post_status' => 'wc-ywraq-new' //will get the new order
) );
// Your post loop
if ( $loop->have_posts() ):
while ( $loop->have_posts() ) : $loop->the_post();
// The ID
$order_id = $loop->post->ID;
// The object from WC_Order find the reference in woocommerce docs
$order = wc_get_order($loop->post->ID);
endwhile;
wp_reset_postdata(); // always
endif;
Here's the reference from github: https://github.com/woocommerce/woocommerce/wiki/wc_get_orders-and-WC_Order_Query
Related
How can I in WooCommerce set all products to virtual?
Apperantly this does not work:
function set_virtual(){
$args = array(
'post_type' => 'product',
'posts_per_page' => -1
);
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post();
//global $product;
$id=get_the_ID();
$post=get_post();
$product=wc_get_product($id);
$product->set_virtual(true);
$name=$product->get_name();
$id=$product.save();
echo "Product (event): $name ($id) should now be virtual ";
//But it does not work!!
endwhile;
wp_reset_query();
}
I want to use it for setting variable products in WooCommerce, which cannot be set virtual in the user interface. To be used on summer camp holiday bookings, concert bookings etc. where the product has a variable price, the "store" is fixed by the size of the camp/event, but you want virtual setting because no product is shipped. (There is no need for the processing step in WooCommerce - Virtual products skip that step)
The real requirement is not to make the product virtual, but to get through with the ordering process since the product stock is not a physical stock which needs to be shipped, but limited space in the event, that I am selling. I found below solution to the problem at WooCommerce.
https://docs.woocommerce.com/document/automatically-complete-orders/
/**
* Auto Complete all WooCommerce orders.
*/
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_order' );
function custom_woocommerce_auto_complete_order( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
}
Please note: This solution will set all your products to act like virtual products. You may included into the themes functions.php, or into a customized plugin in body
This question already has answers here:
Change "add to cart" text if a user has bought specific products in WooCommerce
(1 answer)
Add a purchase condition to WooCommerce products
(1 answer)
Checking if customer has already bought something in WooCommerce
(10 answers)
Display a custom text if user has already bought the current product In Woocommerce
(1 answer)
Change "add to cart" button for purchased products in Woocommerce
(1 answer)
Closed 2 years ago.
I would like to hide the Add-To-Cart-Button on the shop page if a Customer has already purchased this Product (in all his previous orders), in this case I'd like to dispay a notice in place of the button. I have found this Script here
add_shortcode( 'my_purchased_products', 'bbloomer_products_bought_by_curr_user' );
function bbloomer_products_bought_by_curr_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 );
$product_ids_str = implode( ",", $product_ids );
// PASS PRODUCT IDS TO PRODUCTS SHORTCODE
return do_shortcode("[products ids='$product_ids_str']");
}
It works fine, it collects the previous products in $product_ids or $product_ids_str.
Now I'd like to use this in the loop, finding out for every product if its ID is part of the $product_ids Array. I have added the Shortcode [my_purchased_products] in the Shop page.
In the copied template files archive-product.php or content-product.php I'd like to use the $product_ids Array, or maybe the String $product_ids_str, so I changed the last line of the script from
return do_shortcode("[products ids='$product_ids_str']");
to
return $product_ids;
or
return $product_ids_str;
But although the script works fine I cannot access the results, var_dump() gives NULL.
Is there something wrong with the way I return $product_ids or $product_ids_str?
Or is there a better way to achieve the desired result?
Thanks in advance!
I used finally the built-in function wc_customer_bought_product() as follow:
$pid = get_the_ID();
$uid = get_current_user_id();
if( wc_customer_bought_product('', $uid, $pid ) )
echo "already bought";
else
echo "not bought yet";
I'm trying to implement in the code a way to show specific contact forms data to a particular user via ID but I'm having difficulty finding which part of the code to add it to.
$user_ID = get_current_user_id();
if ( $user_ID == ('2') ) {
I'm currently inside the admin-mainpage.php within the plugin files.
It's not as simple as I thought as it doesn't store the form names via db.
Any help would be appreciated.
Forms-list
It looks like Contact Forms 7 is your plugin for the forms portion while CFDB7 is an accompanying plugin that writes the form submissions to the WP database.
Get the Form ID
There are a couple ways to get the form ID. It looks like the easiest path is to look at the shortcode that the CF7 creates. You can see it in their documentation here. The code is something like [contact-form-7 id="4" title="Foo"] with id being the form ID (4 in this case).
Show the Right Form to the Right Person
Assuming you know the user ids and the related form ids you want to show them, you could write a very simple shortcode plugin to display the right forms for the right people. It'd be something like this untested code below.
//[user-form-display]
function user_form_display( $atts ){
$user_id = get_current_user_id();
if ($user_id == 2){
echo do_shortcode('[contact-form-7 id="4" title="Foo"]');
} else if ($user_id == 4){
echo do_shortcode('[contact-form-7 id="88" title="Bar"]');
}
}
add_shortcode( 'user-form-display', 'user_form_display' );
You could then put the shortcode in the regular post field and not edit either the CF7 plugin nor mess with the theme files.
You could also make the shortcode fancier and tie user ids to form ids directly in the shortcode arguments. That would take a bit more effort but is probably worth it.
Getting the Form Data
You could modify the $args to include form ids based on an association with a user id or multiple user ids. The form ids should be a field in that table. That's the example indicated below.
Alternately you could modify how the information is returned based on the same relationships by setting up the if/then statements in the $data_value lines. This is easier probably but messier in the long run.
function specfic_table_data()
{
global $wpdb;
$user_id = get_current_user_id();
if($user_id == 1){
$form_ids = array(4,6);//only returns forms with id 4 and 6 when it's user w id 1
}
$cfdb = apply_filters( 'cfdb7_database', $wpdb );
$data = array();
$table_name = $cfdb->prefix.'db7_forms';
$args = array(
'post_type'=> 'wpcf7_contact_form',
'order' => 'ASC',
'posts_per_page' => 10,
'post__in' => $form_ids,
);
$the_query = new WP_Query( $args );
while ( $the_query->have_posts() ) : $the_query->the_post();
$form_post_id = get_the_id();
$totalItems = $cfdb->get_var("SELECT COUNT(*) FROM $table_name WHERE form_post_id = $form_post_id");
$title = get_the_title();
$link = "<a class='row-title' href=admin.php?page=cfdb7-list.php&fid=$form_post_id>%s</a>";
$data_value['name'] = sprintf( $link, $title );
$data_value['count'] = sprintf( $link, $totalItems );
$data[] = $data_value;
endwhile;
var_dump($data);
}
I am facing very strange issue. I am working on woocomerce based wordpress site, in which I have imported about more than 1 lack product form XML programatically, My problem is product meta data named Related Product saved in database, Displayed in back-end, But not displayed on single product page on front-end. But when I manually update post from back-end then after it displayed. It is not possible for me to manually update more than 1 lack post. So I decided to create function that will update post.
add_action( 'wp_loaded', 'my_update_posts' );
if ( $_REQUEST['test'] == 1 ) {
function my_update_posts() {
$args = array(
'post_type' => 'product',
'numberposts' => -1
);
$myposts = get_posts($args);
//echo "<pre>"; print_r($myposts); die;
foreach ( $myposts as $mypost ) {
if ( $mypost->ID == 17 ) {
//$mypost->title = "test";
wp_update_post( $mypost );
}
}
}
}
So I created this function and tested but it will update/save post data like content and title, and not updating/saving meta data.
I want create function that can save post programatically, including meta data.
The best way to save post data is using the update_post_meta function.
I have no idea how Woocommerce saves the related products. Keep in mind that it might make more then one meta field, maybe even create meta in the other related post.
Hope this helps, your question is a bit vague.
I have 2 questions regarding Woocommerce for Wordpress.
I'm working on a site that sells speakers to the Danish market.
Question one:
Can I detect the IP of a visitor and detect which country the person is from? I guess this can be done with some ClientLocation api.
Can I then disable all shopping relatet pages and buttons if a person is not from Denmark. Fx: hiding the add to cart, cart and checkout.
I still want the persons to be able to see the prices, they should just not have the option to buy them.
Question 2:
Lets say that question one was sucessfull made. Then I would like to show different prices for other contries than Denmark. So if you are visiting the site from one country, the price is XXX and from another country the price is XXXX.
Let's say:
In USA the price is = $500
And in UK the price = £400
(This has nothing to do with currency. The market price is just different in different countries.)
I've looked at this plugin: http://wordpress.org/plugins/woocomerce-price-by-country/
It allowed me to write different prices for each product, but when I testet it with http://geopeeker.com/ I hadn't worked at all.
Can you give me some pointets or some links to some plugins that you know of?
UPDATE
I managed to solve question 1. I store the visitors country in a cookie with IP location XML API And then I could just create an if statement, saying that if the country was not equal to Denmark, then the add to cart, cart etc. should be removed.
So yeah, I would really appreciate it if anyknow could give me an idea on how I can solve question 2.
I'm able to detect country, but not able to specify a price of each product to the given country.
2'nd update:
Just to let any interested readers know, I ended up buying this plugin. which is working perfectly!
For the 2nd part of your question: If you are only using simple product types (without variations) then you can add custom price fields to the product data page and filter the price using woocommerce_get_price_html.
add_filter('woocommerce_get_price_html','so24863612_custom_price');
function so24863612_custom_price(){
global $post;
$_postID = $post->ID;
$product = get_product( $_postID );
$UK_price = get_post_meta($_postID, '_UK_price', true); //loads custom meta data
$return_price = $product->get_regular_price(); //default to regular price
if (!empty($UK_price)) {
$return_price = $UK_price;
}
return $return_price;
}
You can create and save custom fields on the product page like this:
//Display custom fields on product data page in admin
add_action( 'woocommerce_product_options_general_product_data', 'so24963039_display_custom_general_tab_fields' );
function so24963039_display_custom_general_tab_fields() {
global $woocommerce, $post;
$UK_price = get_post_meta( $post->ID, '_UK_price', true );
woocommerce_wp_text_input(
array(
'id' => '_UK_price',
'label' => __( 'UK Price (£)', 'woocommerce' ),
'value' => $UK_price,
'desc_tip' => 'false'
)
);
}
//Save custom fields to access via get_post_meta
add_action( 'woocommerce_process_product_meta', 'so24963039_save_custom_general_tab_fields' );
function so24963039_save_custom_general_tab_fields ($post_id) {
$woocommerce_UK_price = $_POST['_UK_price'];
if( !empty( $woocommerce_UK_price ) )
update_post_meta( $post_id, '_UK_price', esc_attr( $woocommerce_UK_price ) );
}
-----------------For products with Variations----------------------------
WARNING: Variable products are much more complicated and I'm not nearly as confident in this answer as I am with the simple products part above, but here's my current understanding either way. I had some mini-cart display issues that I had to hack around when using this method (which I will explain at the end), but the totals are calculated correctly in both the mini-cart and the regular cart.
First we want to add new fields to each variant on the variation tab of existing products:
add_action( 'woocommerce_product_after_variable_attributes', 'so24963039_variable_fields', 10, 2 ); //Display Fields
function so24963039_variable_fields( $loop, $variation_data ) {
echo '<tr><td>';
woocommerce_wp_text_input(
array(
'id' => '_variant_UK_price['.$loop.']',
'label' => __( 'UK Price (£)', 'woocommerce' ),
'desc_tip' => 'false',
'value' => $variation_data['_variant_UK_price'][0]
)
);
echo '</td></tr>';
}
We also need to add them dynamically whenever the user adds new variants on the edit product page:
add_action( 'woocommerce_product_after_variable_attributes_js', 'so24963039_variable_fields_js' ); //JS to add fields for dynamically added new variations
function so24963039_variable_fields_js(){ //add fields to new variations that get added
echo '<tr><td>';
woocommerce_wp_text_input(
array(
'id' => '_variant_UK_price[ + loop + ]',
'label' => __( 'UK Price (£)', 'woocommerce' ),
'desc_tip' => 'false',
'value' => $variation_data['_variant_UK_price'][0]
)
);
echo '</td></tr>';
}
Then we save changes to the custom fields in the variation meta data:
add_action( 'woocommerce_process_product_meta_variable', 'so24963039_save_variable_fields', 10, 1 ); //Save variation fields
function so24963039_save_variable_fields( $post_id ) {
if (isset( $_POST['variable_sku'] ) ) {
$variable_sku = $_POST['variable_sku'];
$variable_post_id = $_POST['variable_post_id'];
// Variant Tier 1 Price
$_variant_UK_price = $_POST['_variant_UK_price'];
for ( $i = 0; $i < sizeof( $variable_sku ); $i++) {
$variation_id = (int) $variable_post_id[$i];
if ( isset( $_variant_UK_price[$i] ) ) {
update_post_meta( $variation_id, '_variant_UK_price', stripslashes($_variant_UK_price[$i] ) );
}
}
}
}
Now that we have our custom variation meta data, we can access it in the custom price module like so:
add_filter('woocommerce_get_price_html','so24863612_custom_price');
function so24863612_custom_price(){
global $post;
$_postID = $post->ID;
$product = get_product( $_postID );
$product_type = $product->product_type;
$UK_price = get_post_meta($_postID, '_UK_price', true); //covers simple products
if($product_type == 'variation'){ //override with variant prices
$UK_price = get_post_meta($_postID, '_variant_$UK_price', true);
}
$return_price = $product->get_regular_price(); //default to regular price
if (!empty($UK_price)) {
$return_price = $UK_price;
}
return $return_price;
}
Now, I believe that part should have everything working except for the mini-cart display. For some reason it seems like I just couldn't figure out how to get access to the variation meta data to force it to display properly in the mini cart - like I found where the mini-cart display was being generated but I was having trouble getting the right context path to access the custom variable so I ended up having to do that in the template-tags.php and pass an array of custom values to an optional parameter in my custom price function. This feels very 'wrong' in terms of how we should do things, but it gets the job done. I'm very open to hearing the 'correct' solution to this part of the problem.
In template-tags.php:
<div class="small-7 large-7 columns"><?php
$product_title = $_product->get_title();
echo '<a class="cart_list_product_title" href="'.get_permalink($cart_item['product_id']).'">' . apply_filters('woocommerce_cart_widget_product_title', $product_title, $_product) . '</a>';
echo '<div class="cart_list_product_price">';
//original line: echo woocommerce_price($_product->get_price());
/*Custom Price Override Block*/
$_productID = $_product->id;
$product_type = $_product->product_type;
if($product_type == 'variation') {
$custom_field_data = $_product->product_custom_fields;
$regular_price = $custom_field_data['_regular_price'];
$custom_UK_price = $custom_field_data['_variant_UK_price'];
$custom_variant_prices = [$regular_price[0], $custom_UK_price[0]];
echo so24863612_get_custom_price($_productID, $custom_variant_prices );
} else {
echo so24863612_get_custom_price($_productID );
}
/*End Custom Price Override Block*/
echo ' /</div>';
echo '<div class="cart_list_product_quantity">'.__('Quantity', 'woocommerce').': '.$cart_item['quantity'].'</div>';
?></div>
I see your update that you did manage to get the visitor's country and that you can use this to create the if statement to remove the cart. (which is freaking cool, by the way)
Doesn't that answer your question 2, about changing the prices for each visitor? All you have to do is make sure that both prices are stored somewhere, and then just have it echo the Denmark or the UK one.
Prices are specific - custom fields
You mentioned this is NOT currency conversion - so you need to store both values. Add a custom field to the product entry that you edit with that new price, and name it "denmarkprice" or something
I'm not 100% familiar enough with WooCommerce to say what custom field plugin might work, but you could use http://www.advancedcustomfields.com/ if you don't want to just create the custom field yourself and call the variable with the_meta() when you want to display it inside your if else statement.
http://codex.wordpress.org/Custom_Fields