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 . ' ' . '<strike>' . $regular_price . '</strike>' . ' '. $sale_price;
Related
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();
}
I am trying to add a feature to my product detail page. I want the user can see Sold Quantity of the last 24 hrs.
For example, I add code into my function.php file
add_action( 'woocommerce_product_meta_start', 'bbloomer_product_sold_count', 11 );
function bbloomer_product_sold_count() {
global $product;
$units_sold = $product->get_total_sales();
if ( $units_sold ) echo '<div class="itemSold">' . sprintf( __( '%s Sold Items', 'woocommerce' ), $units_sold ) . '</div>';
}
This is showing me all the time sold quantity but I want the last 24 hr. Please guide me on how we can do this really appreciate this. Advance Thank you.
in your case, you can query it manual from the database and build the function like this:
add_action( 'woocommerce_product_meta_start', 'bbloomer_product_sold_count', 11 );
function bbloomer_product_sold_count() {
global $product;
global $wpdb;
$product_id = $product->id();
$date_to = date("Y-m-d H:i:s", strtotime('+24 hours'));
$date_from = date("Y-m-d H:i:s");
$sql = "
SELECT COUNT(*) AS sale_count
FROM {$wpdb->prefix}woocommerce_order_items AS order_items
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_meta ON order_items.order_item_id = order_meta.order_item_id
INNER JOIN {$wpdb->posts} AS posts ON order_meta.meta_value = posts.ID
WHERE order_items.order_item_type = 'line_item'
AND order_meta.meta_key = '_product_id'
AND order_meta.meta_value = %d
AND order_items.order_id IN (
SELECT posts.ID AS post_id
FROM {$wpdb->posts} AS posts
WHERE posts.post_type = 'shop_order'
AND posts.post_status IN ('wc-completed','wc-processing')
AND DATE(posts.post_date) BETWEEN %s AND %s
)
GROUP BY order_meta.meta_value";
$units_sold = $wpdb->get_var($wpdb->prepare($sql, $product_id, $date_from, $date_to));
if ( $units_sold ) echo '<div class="itemSold">' . sprintf( __( '%s Sold Items', 'woocommerce' ), $units_sold ) . '</div>';
}
because woocommerce doesn't provide the function for your case
(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.
I Would like to replace all Regular prices on my WooCommerce store with the Sale Price value and delete the Sale Price values under the wp_postmeta table.
The column post_id is identical for both prices for each product and the column to copy is _sale_price to _price and delete _sale_price.
What query could I run to achieve this?
Here is a pure MySQL query that you are looking for:
First you have to use self join to update _price and _regular_price field
UPDATE `wp_postmeta` AS a,
`wp_postmeta` AS b
SET a.`meta_value` = b.meta_value
WHERE a.post_id = b.post_id
AND a.meta_key IN ('_price', '_regular_price')
AND b.meta_key = '_sale_price'
AND b.meta_value != ''
AND a.`post_id` IN
(SELECT `ID`
FROM `wp_posts`
WHERE `post_type` = 'product'
AND `post_status` = 'publish');
Now to reset sale price and date you have to set it blank
UPDATE `wp_postmeta`
SET `meta_value` = ''
WHERE `meta_key` IN ('_sale_price', '_sale_price_dates_from', '_sale_price_dates_to')
AND `post_id` IN
(SELECT `ID`
FROM `wp_posts`
WHERE `post_type` = 'product'
AND `post_status` = 'publish' );
If you want to delete this fields then use DELETE statement with the WHERE clause, it will solve your purpose.
Also you have to delete WooCommerce product price caching which is stored in wp_options table under _transient_timeout_wc_var_prices_{{post_id}} and _transient_wc_var_prices_{{post_id}} in option_name
DELETE
FROM `wp_options`
WHERE (`option_name` LIKE '_transient_wc_var_prices_%'
OR `option_name` LIKE '_transient_timeout_wc_var_prices_%')
A special thanks to #LoicTheAztec for pointing out the product price caching
Above query is tested and worked for me.
Before running this query do take a database backup
Hope this helps!
Here is a custom function that will copy the sale price to the regular price and will reset the sale price.Regarding the prices in WooCommerce there is:
the active price: '_price'
the regular price: '_regular_price'
the sale price: '_sale_price'
So you need to update the regular price too and to reset all related data for the sale price. Also you need to refresh prices.
This function has an UI that will appear in shop pages or single product pages only for Admins and Shop Manager.
If you have more than 1000 products, the process will be auto split in multiple steps (by 1000 products) to avoid errors when there is too many products.
The SQL query will only select products Ids that have a sale price and not all products. To update/Reset prices I use update_post_meta() function instead of a query, to refresh each product cache...
It looks like:
Starting Updating prices (step one):
Continuing necessary steps:
Updating prices done (end screen):
Important: Before starting this kind of process always make a database backup
Here is that hooked function code:
add_action( 'woocommerce_before_main_content', function(){
// Only admins and shop manargers
if( ! current_user_can( 'edit_products' ) ) return;
global $wpdb;
$products_count = get_option( 'product_prices_update_count' );
// Auto enable multistep price updates for more than 1000 products
$limit = $products_count > 2 ? 2 : false;
if( $limit != false )
$offset = get_option( 'product_prices_update_offset' );
if( empty( $offset ) && $limit != false ) {
$offset = 0;
add_option( 'product_prices_update_offset', $offset );
}
$control_process = $limit != false ? "LIMIT $offset, $limit" : "";
if( ! isset( $_POST['prices_updates'] ) ) $control_process = '';
// 1. First query: Get for all product ids the sale price
$results = $wpdb->get_results( "
SELECT postmeta.post_id, postmeta.meta_value as price
FROM {$wpdb->prefix}postmeta as postmeta
INNER JOIN {$wpdb->prefix}posts as posts ON postmeta.post_id = posts.ID
WHERE posts.post_type LIKE '%product%'
AND postmeta.meta_key = '_sale_price'
AND postmeta.meta_value != ''
ORDER BY posts.ID ASC
$control_process
" );
if( empty( $products_count ) ){
update_option( 'product_prices_update_count', count($results) );
$count = count($results);
} else $count = $products_count;
$remaining = ! empty( $products_count ) && $limit != false ? $count-($offset+$limit) : count($results);
$products_updated = 0;
echo '<div style="border: solid 1px grey; padding: 16px; margin-bottom: 12px;)">
<form class="cart" method="post" enctype="multipart/form-data">';
if( isset( $_POST['prices_updates'] ) && ( $remaining > 0 || ! $limit ) ){
foreach($results as $result){
$post_id = $result->post_id;
$price = $result->price;
// 2. Updating Active and Regular prices
update_post_meta( $post_id, '_price', $price );
update_post_meta( $post_id, '_regular_price', $price );
// 3. Reset Sale price
update_post_meta( $post_id, '_sale_price', '' );
update_post_meta( $post_id, '_sale_price_dates_from', '');
update_post_meta( $post_id, '_sale_price_dates_to', '');
// 4. Refresh product cache
wc_delete_product_transients($post_id);
$products_updated++;
// echo "$post_id ($products_updated), ";
}
}
if( ( ! $limit && ! empty( $products_count ) ) || $remaining <= 0 ){
echo "<p><strong>Process is now finished.</strong><br>
<em>You can remove or comment the code, Thanks</em></p>";
if( isset($_POST['prices_updates'] ) ){
delete_option( 'product_prices_update_offset' );
delete_option( 'product_prices_update_count' );
}
} else {
if( isset( $_POST['prices_updates'] ) ){
update_option( 'product_prices_update_offset', $offset+$limit );
echo "<p>$products_updated products have been updated.<br>";
echo "There is still $remaining remaining products to update.</p>";
} else
echo "<p>There is $remaining products to update.</p>";
$value = empty( $products_count ) ? "Start update" : "Continue update";
echo '<input type="submit" class="button" name="prices_updates" value="'.$value.'" />';
}
echo '</form></div>';
}, 2, 0);
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
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.