How to display variations in the Shop page Woocommerce - php

I want to display variation with the prices instead of regular prices at the front page, not in single item page.
Now: 10-100$
I need:
- Rent 10$
- Buy 100$
To show the prices for variations I use this function in functions.php.
//Add prices to variations
add_filter( 'woocommerce_variation_option_name', `enter code here`'display_price_in_variation_option_name' );
function display_price_in_variation_option_name( $term ) {
global $wpdb, $product;
$result = $wpdb->get_col( "SELECT slug FROM {$wpdb->prefix}terms WHERE name = '$term'" );
$term_slug = ( !empty( $result ) ) ? $result[0] : $term;
$query = "SELECT postmeta.post_id AS product_id
FROM {$wpdb->prefix}postmeta AS postmeta
LEFT JOIN {$wpdb->prefix}posts AS products ON ( products.ID = postmeta.post_id )
WHERE postmeta.meta_key LIKE 'attribute_%'
AND postmeta.meta_value = '$term_slug'
AND products.post_parent = $product->id";
$variation_id = $wpdb->get_col( $query );
$parent = wp_get_post_parent_id( $variation_id[0] );
if ( $parent > 0 ) {
$_product = new WC_Product_Variation( $variation_id[0] );
//this is where you can actually customize how the price is displayed
return $term . ' (' . woocommerce_price( $_product->get_price() ) . ')';
}
return $term;
}
But how can I request the variations in the loop of the shop page? I try to use get_available_variations(); but it didn't work for me.

Related

Display total revenue of a product id in WooCommerce shortcode

I am trying to display the total revenue of a given product ID from WooCommerce via a shortcode. I have code this far with the code however I cannot seem to get it to work correctly by selecting the individual ID, at the moment it is showing it for the whole store.
function get_total_sales( $atts ) {
$atts = shortcode_atts( array(
'id' => ''), $atts );
global $wpdb;
$order_totals = apply_filters( 'woocommerce_reports_sales_overview_order_totals', $wpdb->get_row( "
SELECT SUM(meta.meta_value), ['id'], AS total_sales, COUNT(posts.ID) AS total_orders FROM {$wpdb->posts} AS posts
LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
WHERE meta.meta_key = '_order_total'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( 'wc-" . implode( "','wc-", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed','on-hold', 'processing' ) ) ) . "' )
" ) );
return $order_totals->total_sales;
}
add_shortcode('sales', 'get_total_sales');
I am struggling to find how I can made it specific to the ID and have tried to implement an ID attribute, but it seems to be ignored.
Thank you in advance!
If you just want to get all total sales there is a meta that you can use. This method doesnt check by order statuses.
function get_total_sales_by_product_id( $atts ) {
return get_post_meta($atts['id'], 'total_sales', true);
}
add_shortcode('sales', 'get_total_sales_by_product_id');
To get total sales by list of order statuses try this
function get_total_sales_by_product_id( $atts ){
$atts = shortcode_atts( array(
'id' => ''), $atts );
$product_id = $atts['id'];
if(empty($product_id)) return;
//Add remove order statuses
$order_status = array( 'wc-completed', 'wc-processing' );
global $wpdb;
$order_ids = $wpdb->get_col("
SELECT order_items.order_id
FROM {$wpdb->prefix}woocommerce_order_items as order_items
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
LEFT JOIN {$wpdb->posts} AS posts ON order_items.order_id = posts.ID
WHERE posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", $order_status ) . "' )
AND order_items.order_item_type = 'line_item'
AND order_item_meta.meta_key = '_product_id'
AND order_item_meta.meta_value = '$product_id'
");
$unique_order_ids = array_unique($order_ids);
$total_sales = 0;
foreach ($unique_order_ids as $order_id) {
$order = wc_get_order($order_id);
foreach ($order->get_items() as $item_key => $item ) {
if ($item->get_product()->get_id() == $product_id) {
$total_sales = $total_sales + $item->get_quantity();
}
}
}
return $total_sales;
}
add_shortcode('sales', 'get_total_sales_by_product_id');

Putting regular price and sale price on woocommerce variation dropdown menu

First time posting here so please bear with me. I am using the following code:
function display_price_in_variation_option_name( $term ) {
global $wpdb, $product;
$result = $wpdb->get_col( "SELECT slug FROM {$wpdb->prefix}terms WHERE name = '$term'" );
$term_slug = ( !empty( $result ) ) ? $result[0] : $term;
$query = "SELECT postmeta.post_id AS product_id
FROM {$wpdb->prefix}postmeta AS postmeta
LEFT JOIN {$wpdb->prefix}posts AS products ON ( products.ID = postmeta.post_id )
WHERE postmeta.meta_key LIKE 'attribute_%'
AND postmeta.meta_value = '$term_slug'
AND products.post_parent = $product->id";
$variation_id = $wpdb->get_col( $query );
$parent = wp_get_post_parent_id( $variation_id[0] );
if ( $parent > 0 ) {
$_product = new WC_Product_Variation( $variation_id[0] );
return $term . woocommerce_price( $_product->get_price() );
}
return $term;
}
add_filter( 'woocommerce_variation_option_name', 'display_price_in_variation_option_name' );
This code puts a price next to each item in a variations menu. What I'd like to do is to have it also post a sale price and have the regular price be struck through (as in, here's the regular price and the sale price).
I tried the following:
$regular_price = woocommerce_price( $_product->get_regular_price() );
$sale_price = woocommerce_price( $_product->get_price() );
return $term . $regular_price . $sale_price;
And while that does add in a sale price it also has the sale price and regular prices overlap. I guess what I am looking for is a way to format the prices.
Any help is appreciated.
Thanks
You can add a bit of HTML within the Filter to add spaces and strike-through the original price. You can use following code
$regular_price = woocommerce_price( $_product->get_regular_price() );
$sale_price = woocommerce_price( $_product->get_price() );
return $term . '&nbsp' . '<strike>' . $regular_price . '</strike>' . '&nbsp'. $sale_price;

Is there a way to make a sale price null if the value is 0 wooCommerce including product variations

I have a sheet that is exported from my customers Back end stock system.
It includes sale price and retail price. The problem is for the sale pricing if there is no price they are using "0" as the value which in turn means that when the product update runs the product essentially becomes free
I have tried a few options from here. This one seemed to work the best
add_action ('woocommerce_before_shop_loop_item', 'check_sale_price', 40 );
add_action('woocommerce_before_single_product', 'check_sale_price', 40 );
function check_sale_price() {
global $product;
if ( $product->sale_price == '0' ) {
$price = $product->regular_price;
$product->sale_price = $price;
$product->price = $price;
global $wpdb;
$wpdb->get_results( 'UPDATE wp_postmeta SET meta_value='.$price.' WHERE meta_key="_sale_price" AND post_id='.$product->id, OBJECT );
$wpdb->get_results( 'UPDATE wp_postmeta SET meta_value='.$price.' WHERE meta_key="_price" AND post_id='.$product->id, OBJECT );
}
}
But this did not update all my variable products only simple products
It would be great if this code could also update product sale pricing that is "0" in product variations as well
Tested and works with query you can use it in your function.
Try this (where, $price = "set you price" , $product->id = "product id")
UPDATE wp_postmeta as pm
JOIN wp_postmeta as pm2 ON pm.post_id = pm2.post_id
SET pm.meta_value = ( $price )
WHERE pm.meta_key LIKE '_sale_price'
AND pm2.meta_key LIKE '_price'
AND pm.post_id IN
( SELECT p2.ID
FROM wp_posts AS p
JOIN wp_posts AS p2 ON p2.post_parent = p.ID
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
AND p.ID = $product->id
AND p2.post_type = 'product_variation'
AND p2.post_status = 'publish' );
Try this for update product price
add_action('woocommerce_before_single_product', 'check_sale_price', 40 );
function check_sale_price() {
global $product;
//update product price
if ( $product->get_sale_price() == '0' ) {
$price = $product->get_price();
$product->set_sale_price($price);
$product->set_price($price);
$product->save();
}
}
Try This
add_action('woocommerce_before_single_product', 'check_sale_price', 40 );
function check_sale_price() {
global $product;
//update product price
$available_variations = $product->get_available_variations();
foreach($available_variations as $variation ){
$variation_id = $variation['variation_id'];
$_product = new WC_Product_Variation($variation_id);
if ( $product->get_sale_price() == '0' ) {
$price = $_product->get_price();
$_product->set_sale_price($price);
$_product->set_price($price);
$_product->save();
}
}
$product->save();
}

Get the orders IDs related to a product bought by a customer in Woocommerce

I have the products ids as an array and I would like to get the list of order ids if the customer has purchased that product.
I have the customer purchased product ids with me. Somehow, I have to get the linked order id and cancel that order if customer purchases new product.
To check if a customer has purchased a product I am using the function has_bought_items() from this answer thread: Check if a customer has purchased a specific products in WooCommerce
May be it can be tweaked to get the desired output?
The following custom function made with a very light unique SQL query, will get all the Orders IDs from an array of products IDs (or a unique product ID) for a given customer.
Based on code from: Check if a customer has purchased a specific products in WooCommerce
function get_order_ids_from_bought_items( $product_ids = 0, $customer_id = 0 ) {
global $wpdb;
$customer_id = $customer_id == 0 || $customer_id == '' ? get_current_user_id() : $customer_id;
$statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );
if ( is_array( $product_ids ) )
$product_ids = implode(',', $product_ids);
if ( $product_ids != ( 0 || '' ) )
$meta_query_line = "AND woim.meta_value IN ($product_ids)";
else
$meta_query_line = "AND woim.meta_value != 0";
// Get Orders IDs
$results = $wpdb->get_col( "
SELECT DISTINCT p.ID FROM {$wpdb->prefix}posts AS p
INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON p.ID = woi.order_id
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
AND pm.meta_key = '_customer_user'
AND pm.meta_value = $customer_id
AND woim.meta_key IN ( '_product_id', '_variation_id' )
$meta_query_line
" );
// Return an array of Order IDs or an empty array
return sizeof($results) > 0 ? $results : array();
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
USAGE Examples:
1) For the current logged in customer (and 2 product Ids in an array):
$product_ids = array(37,53);
$order_ids = get_order_ids_from_bought_items( $product_ids );
2) For a defined User ID and one product ID:
$product_id = 53;
$user_id = 72;
$order_ids = get_order_ids_from_bought_items( $product_id, $user_id );

How can I add the correct variation price in a dropdown in woocommerce depending on its variation type?

(Hopefully this make sense)
I need to be able to either display the individual prices of a variation as you go in woocommerce so a customer knows how much the variation difference is or I need the drop down prices to change so that they make sense visually.
I have used the following code
add_filter( 'woocommerce_variation_option_name',
'display_price_in_variation_option_name' );
function display_price_in_variation_option_name( $term ) {
global $wpdb, $product;
$result = $wpdb->get_col( "SELECT slug FROM {$wpdb->prefix}terms WHERE name = '$term'" );
$term_slug = ( !empty( $result ) ) ? $result[0] : $term;
$query = "SELECT postmeta.post_id AS product_id
FROM {$wpdb->prefix}postmeta AS postmeta
LEFT JOIN {$wpdb->prefix}posts AS products ON ( products.ID = postmeta.post_id )
WHERE postmeta.meta_key LIKE 'attribute_%'
AND postmeta.meta_value = '$term_slug'
AND products.post_parent = $product->id";
$variation_id = $wpdb->get_col( $query );
$parent = wp_get_post_parent_id( $variation_id[0] );
if ( $parent > 0 ) {
$_product = new WC_Product_Variation( $variation_id[0] );
$_currency = get_woocommerce_currency_symbol();
return $term . ' ('.$_currency.' '. $_product->get_price() . ')';
}
return $term;
}
but as you will see this from this image it does not display correctly and looks a little confusing.
[https://i.stack.imgur.com/oQ9RH.png][1]
Any help will be much appreciated.

Categories