How get woocommerce product price before and after save - php

I want get and set log for woocommerce variation product price after product price change. (after click on update product)
EX :
Product 1 :
Variation 1 : old price : 10.000 , new price : 20.000
Variation 2 : old price : 30.000 , new price : 50.000
i test wp_insert_post_data filter and save_post_product action
but i can't get old price and two function return new price
How i can get product old price before new price saved in database
**die at the end of function for see result.
add_action('save_post_product', 'save_post_action', 10, 3);
function save_post_action( $post_id, $post, $update ) {
if (get_post_type($post_id) !== 'product') return;
$product = wc_get_product($post_id);
$current_products = $product->get_children();
foreach ($current_products as $variation_id) {
$variable_product = wc_get_product($variation_id);
//$regular_price = $variable_product->get_regular_price();
//$sale_price = $variable_product->get_sale_price();
$price = $variable_product->get_price();
var_dump($price);
}
die;
}

Variable products are saved using Ajax before saving the parent.
So woocommerce_admin_process_variation_object action precedes save product variation.
add_action('woocommerce_admin_process_variation_object', 'get_previous_variation_price', 10, 1);
function get_previous_variation_price($variation) {
$previous_price = $variation->get_price();
}

Related

Overwrite qty of simple product and variation product in the cart, if they are added in Woocommerce

I am the new developer to make the Woocommerce website. I found this useful code in another post. It works to overwrite the stock under product id.
If I have two variation products under the same product id, it will delete all the variation product under same product id in the cart. How can I amend the following code?
add_filter('woocommerce_add_to_cart_validation', 'remove_cart_item_before_add_to_cart', 1, 3);
function remove_cart_item_before_add_to_cart($passed, $product_id, $quantity) {
$already_in_cart = false;
foreach( WC()->cart->get_cart() as $key => $item ){
// Check if the item is already is in cart.
if( $item['product_id'] == $product_id ){
$already_in_cart = true;
$existing_product_key = $key;
break;
}
}
if( $already_in_cart ){
WC()->cart->remove_cart_item($existing_product_key);
}
return $passed;
}
For Example:
Cart
Product A (Blue) x 1 qty
Product A (Red) x 1 qty
What I want is if I try to add 2 qty of Product A (Blue), the cart will only overwrite the quantity of Product A (Blue) and keep the quantity of Product A (Red) remain unchanged.

Enable decimal quantities and stock for WooCommerce products

I want to change the default quantity from the products, from 1 to 0,1 but I can't seem to figure it out.
I tried the following:
function custom_quantity_input_args($args, $product) {
$args['input_value'] = 0.10;
$args['min_value'] = 0.10;
$args['step'] = 0.10;
$args['pattern'] = '[0-9.]*';
$args['inputmode'] = 'numeric';
return $args;
}
The problem with this is that modifies the quantity input from cart as well, which isn't what I want.
To be more specific I want the following:
when I go to the product page I want to show 0,1;
when I go to the cart page I want to show the current quantity;
The solution I mention above shows 0,1 both in product page and in cart page.
I found another solution, but it shows the current quantity both in product and in cart which, again, it's not what I want.
Any ideas?
Based on Decimal quantity step for specific product categories in WooCommerce answer code, try the following revisited code:
// Defined quantity arguments
add_filter( 'woocommerce_quantity_input_args', 'custom_quantity_input_args', 9000, 2 );
function custom_quantity_input_args( $args, $product ) {
if( ! is_cart() ) {
$args['input_value'] = 0.1; // Starting value
}
$args['min_value'] = 0.1; // Minimum value
$args['step'] = 0.1; // Quantity steps
return $args;
}
// For Ajax add to cart button (define the min value)
add_filter( 'woocommerce_loop_add_to_cart_args', 'custom_loop_add_to_cart_quantity_arg', 10, 2 );
function custom_loop_add_to_cart_quantity_arg( $args, $product ) {
$args['quantity'] = 0.1; // Min value
return $args;
}
// For product variations (define the min value)
add_filter( 'woocommerce_available_variation', 'filter_wc_available_variation_price_html', 10, 3);
function filter_wc_available_variation_price_html( $data, $product, $variation ) {
$data['min_qty'] = 0.1;
return $data;
}
// Enable decimal quantities (in frontend and backend)
remove_filter('woocommerce_stock_amount', 'intval');
add_filter('woocommerce_stock_amount', 'floatval');
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Woocomerce - Update max quantity for product variation

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

How to set and update dynamic Stock for similar product in WooCommerce

Problem : I have 3 product similar type or they are same(Same product with different name). If those product should have same Stock. I am not sure it possible or not?
For example:
Product One Stock= 10
Product Two Stock= 10
Product Three Stock= 10
Goal: Want to set/update Same Stock for those product if any of them in order
Result 1: Product One qty 5 in order so new updated Stock
Product One Stock = 10-5 =5
Product Two Stock = 10-5=5
Product Three Stock = 10-5=5
Result 2: Product One qty 5 and Product Two qty 2 in order So total qty of similar product =5+2=7 so new updated stock
Product One Stock = 10-7 =3
Product Two Stock = 10-7=3
Product Three Stock = 10-7=3
To Achieve this I set all similar product in a option like 12,45,133 (product ID) separated by comma
ANd a option field for Common Quantity.
My Code what I am trying
add_action( 'woocommerce_thankyou', 'set_dynamic_quantity');
function set_dynamic_quantity_having_product_id_in_order($order_id){
$order = wc_get_order( $order_id );
$items = $order->get_items();
//getting options value
$similar_product_options = get_option( 'similar_product_options_name' ); // Array of All Options
$vpm_similar_product = $similar_product_options['vpm_similar_product']; //get similar product
$vpm_similar_product_qty = $similar_product_options['vpm_similar_product_qty']; //get dynamic qty = 100
$similar_id = explode( ",", $vpm_similar_product );
//auto update qty if product in order
if(in_array( $order->get_items() , $similar_id )){
foreach ( $items as $item => $value ) {
$quantity = $item->get_quantity();
$new_qty = $vpm_similar_product_qty - $quantity;
//set new quantity to all similar product set in
$vpm_similar_product_qty['vpm_similar_product_qty'] = $new_qty;
foreach ( $similar_id as $item_id => $item_data ) {
update_meta_data( '_qty', $new_qty, $item_id );
update_option('vpm_similar_product_qty',$same_type_product);
}
}
}
}
I assume $vpm_similar_product_qty is a comma separated product IDs. I also assume that you update this value simply by update_option with the options array.
The logic presented here:
loop through the order items
for each order item, check if it is in the "twins" list
accumulate the ordered quantities
Reduce the total quantity from the synced quantity setting value
loop "twins" and update their quantity accordingly
This is an offered solution:
add_action( 'woocommerce_thankyou', 'set_dynamic_quantity_having_product_id_in_order');
function set_dynamic_quantity_having_product_id_in_order($order_id){
$order = new WC_Order( $order_id );
# This protect from double reduction on the same order
if (get_post_meta($order->get_id(), 'shared_products_quantities_updated', true)) return;
$similar_product_options = get_option( 'similar_product_options_name' ); // Array of All Options
$vpm_similar_product = $similar_product_options['vpm_similar_product']; //get similar product
$shared_stock_products = explode( ",", $vpm_similar_product );
// Local Testing $shared_stock_products = array(48, 45, 41);
# First time, set stock level
if (!get_option('vpm_similar_product_qty')) update_option('vpm_similar_product_qty', 100);
# Get Shared stock level
$vpm_similar_product_qty = get_option('vpm_similar_product_qty');
# Count how many twin products bought
$reduce_quantity = 0;
foreach ($order->get_items() as $key => $item){
if ( in_array($item['product_id'], $shared_stock_products ) ){
$reduce_quantity += $item->get_quantity();
}
}
# Sync stock levels according to the shared stock level setting
$updated_quantity = $vpm_similar_product_qty - $reduce_quantity;
foreach ($shared_stock_products as $product_id){
$product = new WC_Product($product_id);
$product->set_stock_quantity( $updated_quantity );
$product->save();
}
# Prevent duplicate qty deduction
add_post_meta($order->get_id(), 'shared_products_quantities_updated', true);
# Sync back the quantity to the shared quantity
update_option('vpm_similar_product_qty', $updated_quantity);
}
There is one issue which you didn't cover though:
The shared stock is 10. Two "twin" products are in cart, one with qty of 8 and one with 5. This will produce a negative stock value. But since this issue is out of this scope, I will not address it.

Get the minimum variation price in WooCommerce

I am a beginner trying to learn Wordpress and have a variable product with prices:
cod Rs 250
online Rs 200
I want to use the minimum price in my themes functions.php.
How will I be able to fetch or get the minimum value?
I want to use in the below code :
function filter_gateways($gateways){
$payment_NAME = 'cod'; //
$min_variation_price = ''; <--------------- minimum variation price
global $woocommerce;
foreach ($woocommerce->cart->cart_contents as $key => $values ) {
// Get the terms, i.e. category list using the ID of the product
$terms = get_the_terms( $values['product_id'], 'product_cat' );
// Because a product can have multiple categories, we need to iterate through the list of the products category for a match
foreach ($terms as $term) {
// 20 is the ID of the category for which we want to remove the payment gateway
if($term->term_id == $min_variation_price){
unset($gateways[$payment_NAME]);
// If you want to remove another payment gateway, add it here i.e. unset($gateways['cod']);
break;
}
break;
}
}
return $gateways;
}
To get the minimum variation active price in WooCommerce from a WC_Product_Variable object:
$variation_min_price = $product->get_variation_price();
It seems that you are trying here to unset 'cod' payment gateway when a cart item min variation price is matching with his product category ID.
Using the WordPress conditional function has_term() will really simplify your code (it accepts term Ids, term slugs or term names for any taxonomy (as 'product_cat' here for product categories).
I suppose that your function is hooked in woocommerce_available_payment_gateways filter hook…
I made some changes in your code as it's a bit outdated and with some errors:
add_filter('woocommerce_available_payment_gateways', 'conditional_payment_gateways', 10, 1);
function conditional_payment_gateways( $available_gateways ) {
// Not in backend (admin)
if( is_admin() )
return $available_gateways;
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// Get the WC_Product object
$product = wc_get_product($cart_item['product_id']);
// Only for variable products
if($product->is_type('variable')){
// Get the Variation "min" price
$variation_min_price = $product->get_variation_price();
// If the product category match with the variation 'min" price
if( has_term( $variation_min_price, 'product_cat', $cart_item['product_id'] ) ){
// Cash on delivery (cod) payment gateway
unset($available_gateways['cod']); // unset 'cod'
break; // stop the loop
}
}
}
return $available_gateways;
}
Code goes in functions.php file of your active child theme (or theme) or also in any plugin file.
This should work (but I can't really test it as it's very specific regarding the product categories ID and the min variation prices)…
All related price methods for variable product type:
// All prices: multidimensional array with all variation prices (including active prices, regular prices and sale prices).
$prices = $product->get_variation_prices();
$prices_for_display = $product->get_variation_prices( true ); // For display
// The min or max active price.
$min_price = $product->get_variation_price(); // Min active price
$min_price_for_display = $product->get_variation_price('min', true); // Min active price for display
$max_price = $product->get_variation_price('max'); // Max active price
$max_price_for_display = $product->get_variation_price('max', true); // Max active price for display
// The min or max regular price.
$min_price = $product->get_variation_regular_price(); // Min regular price
$min_price_for_display = $product->get_variation_regular_price('min', true); // Min regular price for display
$max_price = $product->get_variation_regular_price('max'); // Max regular price
$max_price_for_display = $product->get_variation_regular_price('max', true); // Max regular price for display
// The min or max sale price.
$min_price = $product->get_variation_sale_price(); // Min sale price
$min_price_for_display = $product->get_variation_sale_price('min', true); // Min sale price for display
$max_price = $product->get_variation_sale_price('max'); // Max sale price
$max_price_for_display = $product->get_variation_sale_price('max', true); // Max sale price for display
Related answers:
Disable WooCommerce Payment methods if cart item quantity limit is reached
I think you are looking for that :
add_filter( 'woocommerce_variable_sale_price_html', 'get_min_variation_price_format', 10, 2 );
add_filter( 'woocommerce_variable_price_html', 'get_min_variation_price_format', 10, 2 );
function get_min_variation_price_format( $price, $product ) {
$min_variation_price = $product->get_variation_regular_price( 'min');
return wc_price($min_variation_price);
}

Categories