I am trying to calculate the Base cost of a WooCommerce bookable product and managed to get it done using this:
function modify_baseprice() {
global $post;
$productid = $post->ID;
$product = new WC_Product($productid);
$product_block_price = $product->wc_booking_block_cost;
$product->wc_booking_cost = ($product_block_price*0.6) + 100;
$pricing_data = update_post_meta( $productid, '_wc_booking_cost', $product->wc_booking_cost);
return $pricing_data;
}
add_action( 'woocommerce_bookings_after_booking_base_cost', 'modify_baseprice', 10, 3 );
It does calculate the Base cost correctly but I need to refresh the page twice to see it appearing on the Base cost field. Is there a way that I can get it to appear after the first save?
Since Woocommerce 3 release, CRUD objects have been implemented. It's the case of WC_Product object and also for Woocommerce Bookings plugin. So you can use available Getters and setters methods as properties are not anymore accessible (in most cases).
The following code use this better way (The cost is set in the product without any need of refreshing the page):
add_action( 'woocommerce_process_product_meta_booking', 'modify_bookable_product_base_cost', 100, 1 );
function modify_bookable_product_base_cost( $product_id ){
// Get an instance of the WC_Product object
$product = wc_get_product( $product_id );
// We check that we have a block cost before
if ( $product->get_block_cost() > 0 ){
// Calculation
$new_booking_cost = ( $product->get_block_cost() * 0.6 ) + 100;
$product->set_cost( $new_booking_cost ); // Set the new calculated cost in the product
$product->save(); // Save the product data
}
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
Related
I'm trying to update max quantity for all variations of my variable product to ie 345.
$available_variations = $product->get_available_variations();
foreach ($available_variations as $variation)
{
$variation_ID = $variation->ID;
update_post_meta( $variation_ID , 'max_qty', 345 );
}
It doesn't happen.
You are not using the correct way to get the variation ID and the product meta key max_qty doesn't exist in WooCommerce database on wp_postmeta table for product_variation post type.
Instead you can use the following filter hook to set a specific maximum quantity to product variations:
add_filter( 'woocommerce_available_variation', 'wc_available_variation_max_qty', 10, 3 );
function wc_available_variation_max_qty( $data, $product, $variation ) {
$data['max_qty'] = 345;
return $data;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and work.
Why not set it to 345 by default?
$max_m = $max_l = $max_xl = $max_xxl = $max_xxxl = '345';
if($max_qty != 345){
//Limit Reached error
}
OR
$product->get_available_variations = '345';
if($variation_ID != 345){
$variation_ID->max_qty = 345;
}
Since it's an online shop why not use MySQLi? It's PHP powered so why not?
this way you can do MySQLi->query, and UPDATE the value.
Edited
With WooCommerce, I am using WooCommerce bookings and WooCommerce force sells plugins.
I want to use WooCommerce Force Sells to add one force-sold item per number of person in a booking.
Woocommerce guys already provided a snippet to be added in functions.php which modifies the behavior of Force Sells. With this snippet you can set a fixed quantity (1) of side product to be added :
// only add one force sell item per product no matter how many of the original product are added
function my_wc_force_sell_add_to_cart_product( $product ){
$product['quantity'] = 1;
return $product;
}
add_filter( 'wc_force_sell_add_to_cart_product', 'my_wc_force_sell_add_to_cart_product' );
// when a synced force sell product is updated always set it to 1
function my_wc_force_sell_update_quantity( $quantity, $product ){
return 1;
}
add_filter( 'wc_force_sell_update_quantity', 'my_wc_force_sell_update_quantity' );
What I would like to do: Replacing the fixed quantity (1) with a function retrieving the number of people specified in the booking.
Any help would be awesome.
I think I found it !
function my_wc_force_sell_add_to_cart_product( $product ){
foreach(WC()->cart->get_cart() as $cart_item) {
// The item persons count
$person = array_sum( $cart_item['booking']['_persons'] );
}
$product['quantity'] = $person;
return $product;
}
add_filter( 'wc_force_sell_add_to_cart_product', 'my_wc_force_sell_add_to_cart_product' );
// when a synced force sell product is updated always set it to 1
function my_wc_force_sell_update_quantity( $quantity, $product ){
return 1;
}
add_filter( 'wc_force_sell_update_quantity', 'my_wc_force_sell_update_quantity' );
I have a custom field in Woocommerce variation products and I try to update that field wherever there is a backorder. This is the code
add_action( 'woocommerce_product_on_backorder', 'reduce_second_stock' );
function reduce_second_stock( $array ){
$temp = get_post_meta($array['product']->ID, 'second_stock', true);
update_post_meta( $array['product']->ID, 'second_stock', $temp - $array['quantity'] );
}
The custom field is called second_stock which is just a number. What I try to do is to reduce that number based on the backorder quantity of that order.
However, even if the regular stock of the product is updated, my custom field stays the same.
With this hook, $array['product'] is the WC_Product Object, so to get the product Id you need to use the related method get_id()… Since WooCommerce 3 and CRUD Objects, you can use directly the WC_Data methods get_meta(), update_meta_data() and save() on the WC_Product Object like:
add_action( 'woocommerce_product_on_backorder', 'reduce_second_stock' );
function reduce_second_stock( $array ){
if( $original_stock = $array['product']->get_meta('second_stock') ) {
$array['product']->update_meta_data( 'second_stock', ( $original_stock - $array['quantity'] ) );
$array['product']->save();
}
}
Code goes in function.php file of your active child theme (or active theme). It should work.
I have a setup with Woocommerce "Variable Products" where the only variation is 'size' attribute: 15 grams, 100 grams, 250 grams. What I want to do is use that variation amount to pass to the Woo wc-stock-functions, so that when a product variation '15 grams' is purchased, the overall stock goes down by 15, not 1.
Inside Woo, there is file wc-stock-functions (http://hookr.io/plugins/woocommerce/3.0.6/files/includes-wc-stock-functions/) - and this even gives a filter, woocommerce_order_item_quantity. I want to use this to multiply the inventory number by the # of grams, and to reduce inventory this way by grams.
I'm trying this:
// define the woocommerce_order_item_quantity callback
function filter_woocommerce_order_item_quantity( $item_get_quantity, $order,
$item ) {
$original_quantity = $item_get_quantity;
$item_quantity_grams = $item->get_attribute('pa_size');
// attribute value is "15 grams" - so remove all but the numerals
$item_quantity_grams = preg_replace('/[^0-9.]+/', '', $item_quantity_grams);
// multiply for new quantity
$item_get_quantity = ($item_quantity_grams * $original_quantity);
return $item_get_quantity;
};
// add the filter
add_filter( 'woocommerce_order_item_quantity',
'filter_woocommerce_order_item_quantity', 10, 3 );
but am getting internal server error as a response right now.
Does anyone have an idea of what I'm doing wrong with the above code? Thanks for any help.
First error is in $item->get_attribute('pa_size'); as $item is an instance of WC_Order_Item_Product object and get_attribute() method doesn't exist for WC_Order_Item_Product Class.
Instead you need to get the an instance of the WC_Product object using get_product() method from WC_Order_Item_Product Class…
So your code should be:
add_filter( 'woocommerce_order_item_quantity', 'filter_order_item_quantity', 10, 3 );
function filter_order_item_quantity( $quantity, $order, $item )
{
$product = $item->get_product();
$term_name = $product->get_attribute('pa_size');
// The 'pa_size' attribute value is "15 grams" And we keep only the numbers
$quantity_grams = preg_replace('/[^0-9.]+/', '', $term_name);
// Calculated new quantity
if( is_numeric ( $quantity_grams ) && $quantity_grams != 0 )
$quantity *= $quantity_grams;
return $quantity;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Note: This hooked function is going to reduce the stock quantity based on that new returned increased quantity value (in this case the real quantity multiplied by 15)
I am trying to change the price of the product based on location.
For this i am using wc fields factory to create number of fields for locations and updating the price and based on IP i am finding the city(location) and i am fetching the custom field value.
Using
function return_custom_price($price, $product) {
global $post, $blog_id;
$price = get_post_meta($post->ID, '_regular_price');
$post_id = $post->ID;
$price = ($price[0]*2.5);
return $price;
}
add_filter('woocommerce_get_price', 'return_custom_price', 10, 2);
Its working fine, but when i go to view Cart there it showing product price as 0
like this:
Please help me out in this.
Thanks.
Update:
The product meta data '_regular_price' is not a custom field but the product regular price, that you can get directly using WC_Product methods and magic properties directly on the $product object.
If you look to your function you have 2 arguments: $price (the product price) and the $product (the product object)… So you don't need to use any global variables as you got already $product object, that you can use.
Here is the updated code:
add_filter('woocommerce_get_price', 'product_custom_price', 10, 2);
function product_custom_price($price, $product) {
$custom_price = $product->get_regular_price();
return $custom_price * 2.5;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Please see the cart screenshots:
1) The cart without using this code (before):
2) The cart using this the code (after):
As you can see, this code works perfectly and display the regular prices in cart items.
The OP is using this code with a custom field:
add_filter('woocommerce_get_price', 'product_custom_price', 10, 2);
function product_custom_price($price, $product) {
$custom_price = get_post_meta($product->id, 'custom_key', true);
return $custom_price;
}