echo woocommerce stock quantity of a particular product id - wordpress

As the title says, how do i echo the stock quantity of a particular product id? Let's say the product id is "1100" and i want the stock quantity to appear in a page that is not part of the product archive. Is that possible?
For example, in an empty page, it should appear as
"Product A leftover stock: 10"
I am just learning to code and have come up with the following, but no result appear:
function nntest(){
global $woocommerce;
global $product;
$product_id = 1100;
echo $product->get_stock_quantity();
}
Thanks!

You can use get_post_meta() function to get values from database.
this values are stored in wp_postmeta table.
$stock = get_post_meta( $post->ID, '_stock', true );

Another option if you want to work with the actual WC_Product class:
$product_id = 1100;
$product = wc_get_product($product_id);
echo $product->get_stock_quantity();

If you just want to check whether the product is in stock or out of stock use:
$stock = get_post_meta( $post->ID, '_stock_status', true );
It would either return 'instock' or 'outofstock' depending on the stock status.
If you have enabled the option "Enable stock management at product level" and you want stock quantity, use:
$stock = get_post_meta( $post->ID, '_stock', true );

Related

Woocommerce Updating products price with php does not trigger price change notification

I was playing around with php code where i change price for a certain product. Also i am using a plugin that notify's by email once price fells below some amount. The product price updates with no issues also appears with new price in the product list view, but sadly does not trigger the notification plugin. The strange thing is when i go to product edit and click update i immediately get the notification email.
The php code i am using currently:
$ppt = $value / $divider;
$product = wc_get_product($product_id);
print_r($product);
// Mark product as updated
update_post_meta($product_id, '_price', $ppt );
update_post_meta($product_id, '_regular_price', $ppt );
update_post_meta($product_id, '_sync_updated', true );
$product->save();
}
wp_reset_query();
Thank you in advance!
You should use WC_Product setter instead update_post_meta.
Try this (not tested) :
$ppt = $value / $divider;
$product = new WC_Product( $product_id );
// Mark product as updated
$product->set_price( $ppt );
$product->set_regular_price( $ppt );
$product->save();
}
wp_reset_query();

Get customer custom meta on order

I just want to ask how to display custom post meta that I created on customer order detail page on frontend.
Like for example I want to get the value of this meta receive_newsletter on success order detail page on Woocommerce.
Thanks,
JM
You can try this:
$user_id = get_current_user_id();
$key = 'receive_newsletter';
$single = true;
$meta = get_user_meta( $user_id, $key, $single );
echo $meta;
It is depend on where you want to show on order detail page.
For example this hook: do_action( 'woocommerce_order_details_after_order_table', $order );
You can use:
add_action('woocommerce_order_details_after_order_table','wn_display_receive_newsletter');
function wn_display_receive_newsletter($order){
$oder_id = $order->get_id();
$receive_newsletter = get_post_meta('receive_newsletter',$oder_id,true);
echo $receive_newsletter;
}
If you saved "receive_newsletter" meta to user, you can use this
add_action('woocommerce_order_details_after_order_table','wn_display_receive_newsletter');
function wn_display_receive_newsletter($order){
$user_id= $order->get_user_id();
$receive_newsletter = get_user_meta('receive_newsletter',$user_id,true);
echo $receive_newsletter;
}

Create a Woocommerce product sold in units of gram

I would like to create a product in WooCommerce that is sold in units of gram.
The customer would enter the number of grams they want (in an input field) on the product page, and the price would be computed on the fly and added to the cart.
My question is: is this possible, and if so, can someone give me just a "big picture" idea of how I would implement it?
I don't need line-by-line code, just hoping someone with more knowledge of the structure of Woo can guide me on how to best attack the problem.
I already have parts of it worked out:
I can decide that the price entered for the product is the price per
100 grams, so that is how the seller will enter the price.
Then I can
write a little bit of Javascript to compute the price on the fly and
display it on the page as the user types the amount they want. No
problem.
But... I think every discrete product in Woo needs to have its own price.. So for example, if a customer wants 123g of a product, it seems like I might have to create a variation on the fly for that specific price/amount, and then add that to the cart. Which (judging by this) looks non-trivial and a little hacky. Is there a better way to do this?
WooCommerce has an option to show the weights as grams.
The following code will display the KG weights as grams on the WooCommerce templates :
// Convert the product weight
function ag_woocommerce_product_get_weight( $weight ) {
// Only convert if we have a weight
if ($weight) {
// The weight is in KGS, and we want grams, to multiple by 1000
$weight = $weight * 1000;
}
return $weight;
};
// add the filter
add_filter( 'woocommerce_product_get_weight', 'ag_woocommerce_product_get_weight', 10, 1 );
Hope this might help. Cheers!
There is a free plugin for WooCommerce that allows you to input a unit of measure (UOM) for each product:
https://wordpress.org/plugins/woocommerce-unit-of-measure/
I found this plugin that does pretty much exactly what I need-- https://woocommerce.com/products/measurement-price-calculator/
It's easier and quicker to give you that real example, than explain step by step… You will see which hooks are used for all steps or tasks.
You dont need variable products or generate a variation on the fly.
You just need to set on each simple product the price for one gram (or any other base). Now in this code, you can target those products with:
an array of product Ids
or by product categories (or even product tags).
Your concern is about the way to pass the data in the cart, to update the final price for each product and display the chosen grams amount in cart, checkout and in the order.
So in each product you will only set the price by gram… (or you can also make changes in the code and set the product price for 100 grs or even any other base).
The code:
// Add a product custom field "grams_quantity" that will update the displayed price
add_action('woocommerce_before_add_to_cart_button', 'special_product_by_grams', 25);
function special_product_by_grams(){
global $product;
// HERE Define the special product IDs sold by grams
$targeted_product_ids = array(37);
// or HERE Define a product categories (ids, slugs or names)
$categories = array('sold-by-gram');
// Only for products sold by gram
$product_id = $product->get_id();
if ( ! ( in_array( $product_id, $targeted_product_ids ) || has_term( $categories, 'product_cat', $product_id ) ) ) return;
?>
<div class="grams-field">
<label for="grams_quantity"><?php _e('Grams: ','woocoomerce'); ?><span></span><br>
<input type="number" step="1" name="grams_quantity" class="grams_quantity" id="grams_quantity" value="1">
</label>
</div><br>
<script type="text/javascript">
(function($){
// variables initialization
var priceByGram = <?php echo wc_get_price_to_display( $product ); ?>,
currencySymbol = $(".woocommerce-Price-currencySymbol").html(),
updatedPrice;
// On live event: imput number fields
$('input#grams_quantity').on( "click blur", function(){
updatedPrice = ($(this).val() * priceByGram).toFixed(2);
$(".woocommerce-Price-amount.amount").html('<span class="woocommerce-Price-amount amount">'+updatedPrice+' '+currencySymbol+'</span>');
console.log("event"); // <== To be removed
});
})(jQuery);
</script>
<?php
}
// Save the "grams_quantity" custom product field data in Cart item
add_filter( 'woocommerce_add_cart_item_data', 'save_in_cart_the_custom_product_field', 10, 2 );
function save_in_cart_the_custom_product_field( $cart_item_data, $product_id ) {
if( isset( $_POST['grams_quantity'] ) ) {
$cart_item_data[ 'grams_quantity' ] = $_POST['grams_quantity'];
// When add to cart action make an unique line item
$cart_item_data['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'custom_data', $_POST['grams_quantity'] );
}
return $cart_item_data;
}
// Update product price by grams in cart and checkout
add_filter( 'woocommerce_before_calculate_totals', 'update_prices_by_gram', 10, 1 );
function update_prices_by_gram( $cart_object ) {
// HERE Define the special product IDs sold by grams
$targeted_product_ids = array(37);
// or HERE Define a product categories (ids, slugs or names)
$categories = array('sold-by-gram');
foreach ( $cart_object->get_cart() as $cart_item ) {
// Only for products sold by gram
$product_id = $cart_item['product_id'];
if ( in_array( $product_id, $targeted_product_ids ) || has_term( $categories, 'product_cat', $product_id ) ){
// Get an instance of the WC_Product object and the
$product = $cart_item['data'];
$grams = $cart_item['grams_quantity'];
// Method is_on_sale() manage everything (dates…)
$product->set_price( $product->get_price() * $grams);
}
}
}
// Render "grams_quantity" the custom product field in cart and checkout
add_filter( 'woocommerce_get_item_data', 'render_product_custom_field_meta_on_cart_and_checkout', 10, 2 );
function render_product_custom_field_meta_on_cart_and_checkout( $cart_data, $cart_item ) {
$custom_items = array();
if( !empty( $cart_data ) )
$custom_items = $cart_data;
if( isset( $cart_item['grams_quantity'] ) )
$custom_items[] = array(
'name' => __( 'Grams', 'woocommerce' ),
'value' => sanitize_text_field( $cart_item['grams_quantity'] ),
'display' => sanitize_text_field( $cart_item['grams_quantity'] ),
);
return $custom_items;
}
// Save "grams_quantity" to the order items meta data
add_action('woocommerce_add_order_item_meta','add_product_custom_fiel_to_order_item_meta', 1, 3 );
function add_product_custom_fiel_to_order_item_meta( $item_id, $item_values, $item_key ) {
if( isset( $item_values['grams_quantity'] ) )
wc_update_order_item_meta( $item_id, 'Grams', sanitize_text_field( $item_values['grams_quantity'] ) );
}
Code goes in function.php file of your active child theme (or active theme) or in any plugin file.
Tested and works.

How do I tweak WooCommerce Discount Display

I have a WordPress site that uses WooCommerce plug-in. When a discount is applied to a product, the cart displays the price as crossed out with the discounted price at the bottom.
I would like to have a message with the last date of the discount, something like "$100-early bird rate applies up to 2015-09-30". How would I tweak the discount display on the cart or is there a plug-in for this?
Thanks in advance
Sale end date is stored as product meta, you can pull it using get_post_meta , the filter to use is get_price_html
add_filter( 'woocommerce_get_price_html', 'so32504214_price_html', 20, 2 );
function so32504214_price_html( $price, $product ){
$date = get_post_meta( $product->id, '_sale_price_dates_to', true );
if( strstr( $price, "<ins>" ) && "" != $date ) {
$date = date("Y-m-d", $date);
return str_replace( '</ins>', ' </ins> - early bird rate applies up to '. $date , $price );
}
return $price;
}

Woocommerce - Product price depending on country

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

Resources