Update all WooCommerce product prices to 2 decimals in database - php

Many of my products have prices like £3.4560 etc. I need them to rounded and stripped to just 2 in the database.
The output of 2 decimal places in WooCommerce is not enough and fails to work with a Tax Toggle plugin.
Is there a database query that can do this?
I've seen some bits on Rounding and Truncate but not sure how to execute this as my knowledge is poor.
Any help is appreciated.

Update 2: (Added some code to clear all related product transient cache)
Here is some code that will update all the product prices (make a database backup before):
global $wpdb;
$postmeta = $wpdb->prefix . "postmeta";
$posts = $wpdb->prefix . "posts";
// 1. First query: Get all prices
$results = $wpdb->get_results( "
SELECT $postmeta.*
FROM $postmeta
INNER JOIN $posts ON $postmeta.post_id = $posts.ID
WHERE $posts.post_type LIKE '%product%'
AND $postmeta.meta_key LIKE '%price%'
AND $postmeta.meta_value != ''
ORDER BY $postmeta.meta_id ASC
" );
// iterating through each price and update it
foreach($results as $result){
$meta_id = $result->meta_id;
$post_id = $result->post_id;
$meta_key = $result->meta_key;
$meta_value = number_format( $result->meta_value, 2 );
// 2. Udating prices query
$wpdb->query( $wpdb->prepare( "
UPDATE $postmeta
SET meta_id = $meta_id, post_id = $post_id, meta_key = '$meta_key', meta_value = '$meta_value'
WHERE $postmeta.meta_id = %d
", $meta_id ) );
// 3. Clear all related product transient cached data (refresh prices)
wc_delete_product_transients($post_id);
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Once saved, just browse any page of your site, check your database wp_postmeta table searching for ‰price‰ LIKE meta_key. Now you can remove this code.

Related

Change Woocommerce product category name with a SQL query

I want to update in Wordpress, many product_category names,retrieving them from a csv file.
the csv file header is just: (ID;Product_category_Name)
I have 900 categories and subcategories, in hierarchical structure.
is it possible to search in the DB for a category by ID and update the category name ?
will that keep the hierarchical structure correct ?
can i include in the names some chars like 'ö' 'ä' or 'å' in UTF-8?
I can use wp php functions or direct sql commands.
This answer, answers your question title, but not all other questions (see how to ask).
You can use the following SQL query (making a database backup before):
UPDATE wp_terms as a
JOIN wp_term_taxonomy b ON a.term_id = b.term_id
SET a.name = 'new_name',
a.slug = 'new_slug'
WHERE b.taxonomy = 'product_cat'
AND a.name = 'old_name'
Where you will need to replace:
new_name by your new product category name
new_slug by your new product category slug (in lowercase and "-" replace white spaces)
old_name by your Old product category name (the one you want to replace)
You can also use the following function with the same SQL query:
function rename_product_category( $old_name, $new_name ){
global $wpdb;
// Check that the new name doesn't exist
if( term_exists( $new_name, 'product_cat' ) )
return __("Your new product category term name already exist");
// Check that the old name exist
if( ! term_exists( $old_name, 'product_cat' ) )
return __("Your old product category term name doesn't exist");
$new_slug = sanitize_title( $new_name );
$result = $wpdb->query("
UPDATE {$wpdb->prefix}terms as a
JOIN {$wpdb->prefix}term_taxonomy b ON a.term_id = b.term_id
SET a.name = '$new_name',
a.slug = '$new_slug'
WHERE b.taxonomy = 'product_cat'
AND a.name = '$old_name'
");
if($result)
return sprintf(
__("The product category %s has been renamed to %s."),
'"<strong>' . $old_name . '</strong>"',
'"<strong>' . $new_name . '</strong>"'
);
else
return __("Something is wrong!.");
}
Code goes in function.php file of your active child theme (or active theme).
USAGE (Let's say tha you rename "Clothing" product category to "Wear"):
echo rename_product_category( 'Clothing', 'Wear' );
It will display if the product category has been renamed or not. Tested and works.

Woocommerce SKU Generator: Generate a sku for all variations same as parent sku

i need a simply function that allow me to add or replace empty sku code for variation in my published product with parent sku of product.
is there a way to obtain this work?
Updated: To replace empty SKU code for variation in your published product with the parent SKU (the variable product SKU), try this function that will only work for admin user role.
Do a database backup before runing this
To run this function, browse your shop page:
It will update 2500 empty variations SKU each time.
A message will display the count of updated variations.
Each time you will need to reload the page to process 2000 variations SKUs.,
When all variations SKUs will be updated, a message let you know that the job is done.
The code:
add_action('woocommerce_before_main_content', 'update_variations_sku', 100 );
function update_variations_sku(){
global $wpdb;
$results = $results2 = array();
$limit = 2500; // Number of variations to process
// The SQL query (get the variations with empty sku and their parent product ID)
$query = $wpdb->get_results( "
SELECT p.ID, p.post_parent
FROM {$wpdb->prefix}posts as p
INNER JOIN {$wpdb->prefix}postmeta as pm ON p.ID = pm.post_id
WHERE p.post_type LIKE 'product_variation'
AND p.post_status LIKE 'publish'
AND pm.meta_key LIKE '_sku'
LIMIT $limit
" );
if( count($query) == 0 ){
echo "<p><pre>The job is finished, you can remove the code</pre></p>";
return; // exit
}
// Loop through variation Ids and get the parent variable product ID
foreach( $query as $value )
$results[$value->post_parent][] = $value->ID;
// Loop through variation Ids and set the parent sku in related empty variations skus
foreach($results as $parent_id => $variation_ids){
$parent_sku = get_post_meta( $parent_id, '_sku', true );
$count = 0;
foreach($variation_ids as $variation_id){
$count++;
update_post_meta( $variation_id, '_sku', $parent_sku.'-'.$count );
}
}
if( count($query) < $limit ){
echo "<p><pre>The job is finished, you can remove the code <br>$count variations SKUs have been updated</pre></p>";
} else {
echo "<p><pre>$count variations SKUs have been updated (continue reloading the page again)</pre></p>";
}
}
Code goes in function.php file of your active child theme (or theme).
Tested and works.

Get a previous order number WooCommerce

I am trying to get previous order number from the specified order number for example there are 5 orders we have.
1780
1781
1782
1784
1786
Now if i specifiy the order number
wc_custom_get_previous_order_number(1784)
I should get 1782. I have tried multiple solutions. For example :
add_filter( 'woocommerce_order_number', 'custom_woocommerce_order_number', 1, 2 );
function custom_woocommerce_order_number( $oldnumber, $order ) {
$lastorderid = $order->id-1; // here is i am trying to get previous order number.
// other code...
}
You could build your own function with a SQL query with 2 arguments:
$order_id is the starting order ID.
$limit is the number of orders Ids to get from.
The function code:
function get_orders_from( $order_id, $limit = 1 ){
global $wpdb;
// The SQL query
$results = $wpdb->get_col( "
SELECT ID
FROM {$wpdb->prefix}posts
WHERE post_type LIKE 'shop_order'
AND ID < $order_id
ORDER BY ID DESC
LIMIT $limit
" );
return $limit == 1 ? reset( $results ) : $results;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
USAGE (examples):
1) To get the previous order ID from the current $order_id you will use in your code:
$previous_order_id = get_orders_from( $order_id );
You will get directly the previous order ID…
2) To get the 3 previous orders IDs from order ID 1784:
// Get the array of orders_ids
$orders_ids = get_orders_from( 1784, 3 );
// Converting and displaying a string of IDs (coma separated)
echo implode( ', ', $orders_ids );
You will get: 1780, 1781, 1782

Force woocommerce product variable dropdowns

I am using woocommerce and have 5 variable products on one page. They all use a attributes of height, width and color. What I would like to do is, if product one selects color of red, I want it also to be selected in the other 4 products. Same for height and width.
I thought this would be as simple as just forcing the dropdown selection with jQuery. So I started looking and I found a few things. They all seemed to be cloning the html into the field of product-2. So if we selected red in product-1, product-2 would have 2 red as options in the dropdown with the clone selected.
I ultimately tweaked something I had found to .change instead of .clone. I used the name because the select id's are the same on all products.
jQuery("select[name='wccp_attribute_pa_length[1488195634]'").change(function() {
alert('working');
if (jQuery(this).data('options') == undefined) {
/*Taking an array of all options-2 and kind of embedding it on the select1*/
jQuery(this).data('options', jQuery('select[name="component_1486761669_bundle_attribute_pa_length_186695"] option').change());
}
var id = jQuery(this).val();
var options = jQuery(this).data('options').filter('[value=' + id + ']');
jQuery('select[name="component_1486761669_bundle_attribute_pa_length_186695"]').html(options);
});
At first glance it seemed to be doing the trick. It visually changed the dropdown in the second product. However if I select a different variation option manually(such as color) it reverts to the first option of the dropdown. And secondly this is not updating the product price. Its as if woocommerce doesnt know the variation is selected.
I am not married to using the above code if anyone knows of a better way. I tried looking for some kind of product filter but I came up empty in my search. I am a noob with woocommerce.
I am really stuck. any help is appreciated, as always.
Cheers
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] );
return $term . ' (' . woocommerce_price( $_product->get_price() ) . ')';
}
return $term;
}

Woocommerce - Trying to get variable product quantity sum in admin

as in title, i'm trying to get sum of my variable product (for each product) in admin instead of 'out-of-stock' or 'in-stock' indication. I've variable product so i need sum of one variation to get all my product (ive a pant in different size and different colour but i need only sum of all size). Anyone got this before me?
Thanks in advance, Francesco
Finally i found solution.
First of all added this
function add_qty_admin( $column ) {
if (!isset($columns['total_qty']))
$columns['total_qty'] = "Quantità";
return $columns;
}
add_filter( 'manage_posts_columns', 'add_qty_admin' );
to functions.php in order to have a column in my backend.
Then i've added also this
function admin_post_data_row($column_name, $post_id)
{
global $wpdb;
switch($column_name)
{
case 'total_qty':
$query = "SELECT sum(meta_value)
FROM $wpdb->posts AS p, $wpdb->postmeta AS s
WHERE p.post_parent = %d
AND p.post_type = 'product_variation'
AND p.post_status = 'publish'
AND p.id = s.post_id
AND s.meta_key = '_stock'";
$product_qty = $wpdb->get_var($wpdb->prepare($query,$post_id));
if ($product_qty) echo $product_qty;
break;
default:
break;
}
}
add_action( 'manage_posts_custom_column', 'admin_post_data_row', 10, 2);
where $query is SQL query that sum all _stock value in postmeta table for post_parent posts that are the variations of post_id.
Sorry for my poor english (i'm italian), i hope this code can be helpful fot other people.
Francesco.

Categories