I want to apply a discount if a custom checkout field is filled.
That's the code i use to generate the discount:
function custom_wc_add_discount() {
$0tax = WC()->cart->subtotal * -0.22;
WC()->cart->add_fee( '0% tax', $0tax );
}
add_action( 'woocommerce_cart_calculate_fees','custom_wc_add_discount' );
And I want to condition it with something like this:
if ( $_POST[billing_vat]){
Edit: I solved the condition problem creating a coupon like this
add_action( 'woocommerce_checkout_process', 'apply_tax_coupon' );
function apply_tax_coupon() {
global $woocommerce;
$coupon_code = '0%val';
$woocommerce->cart->remove_coupon( $coupon_code );
if ( $_POST[billing_vat]){
$woocommerce->cart->add_discount( $coupon_code );
}
wc_print_notices();
}
But now in checkout page it doesn't show the discounted total.
Any help is appreciated.
You have some problems :
You can't start php var with a number
you missed the quote arroung billing_vat in the condition
Try resolve this and we will see if there is other things to do.
Related
I would like to add a function that is triggered every time that the stock quantity of a product will be changed in the admin product page, such that this function will not allow any reduce of the stock value - but only increase.
This is to prevent an admin user to reduce the stock quantity of the products.
Of course, this function should not be triggered if a product will be in an order, since then of course I would like the stock quantity to be reduced.
I tried the following function in the functions.php but unfortunately did not work.
Since I'm new to woocommerce and php, any ideas that could provide a solid solution to the problem?
// get old and new product stock quantity
function get_old_and_new_product_quantity_stock( $sql, $product_id_with_stock, $new_stock, $operation ) {
$product = wc_get_product( $product_id_with_stock );
$old_stock_quantity = $product->get_stock_quantity();
$new_stock_quantity = $new_stock;
echo $old_stock_quantity, $new_stock_quantity;
if ($new_stock_quantity < $old_stock_quantity) {
$new_stock = $old_stock_quantity;
$new_stock_quantity = $old_stock_quantity;
}
return $sql;
}
add_filter( 'woocommerce_update_product_stock_query', 'get_old_and_new_product_quantity_stock', 10, 4 );
You can use the update_post_meta action hook to check if the new value is less than the previous value and display error message.
This will work for quick edit and for product edit page. But the wp_die on product page will look bad so use the javascript to prevent submitting on product edit page (there was another question about it yesterday)
Be sure to test this snippet and create some orders that will reduce the stock automatically. I added is_admin() check but please do a good test.
add_action( 'update_post_meta', 'prevent_reducing_stock_metadata', 10, 4 );
function prevent_reducing_stock_metadata( $meta_id, $post_id, $meta_key, $meta_value ) {
// Check if the meta key is _stock and the new value is less than the previous value
if ( '_stock' == $meta_key && $meta_value < get_post_meta( $post_id, '_stock', true ) ) {
// Check if this is an update from the WordPress admin area
if ( is_admin() ) {
wp_die( __( 'Error: You cannot reduce the stock level for this product.' ), 'error' );
}
}
}
I am trying to change product price in cart using the following function:
add_action( 'woocommerce_before_shipping_calculator', 'add_custom_price'
);
function add_custom_price( $cart_object ) {
foreach ( $cart_object->cart_contents as $key => $value ) {
$value['data']->price = 400;
}
}
It was working correctly in WooCommerce version 2.6.x but not working anymore in version 3.0+
How can I make it work in WooCommerce Version 3.0+?
Thanks.
Update 2021 (Handling mini cart custom item price)
With WooCommerce version 3.0+ you need:
To use woocommerce_before_calculate_totals hook instead.
To use WC_Cart get_cart() method instead
To use WC_product set_price() method instead
Here is the code:
// Set custom cart item price
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 1000, 1);
function add_custom_price( $cart ) {
// This is necessary for WC 3.0+
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Avoiding hook repetition (when using price calculations for example | optional)
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
$cart_item['data']->set_price( 40 );
}
}
And for mini cart (update):
// Mini cart: Display custom price
add_filter( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 3 );
function filter_cart_item_price( $price_html, $cart_item, $cart_item_key ) {
if( isset( $cart_item['custom_price'] ) ) {
$args = array( 'price' => 40 );
if ( WC()->cart->display_prices_including_tax() ) {
$product_price = wc_get_price_including_tax( $cart_item['data'], $args );
} else {
$product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
}
return wc_price( $product_price );
}
return $price_html;
}
Code goes in functions.php file of your active child theme (or active theme).
This code is tested and works (still works on WooCommerce 5.1.x).
Note: you can increase the hook priority from 20 to 1000 (or even 2000) when using some few specific plugins or others customizations.
Related:
Set cart item price from a hidden input field custom price in Woocommerce 3
Change cart item prices based on custom cart item data in Woocommerce
Set a specific product price conditionally on Woocommerce single product page & cart
Add a select field that will change price in Woocommerce simple products
With WooCommerce version 3.2.6, #LoicTheAztec's answer works for me if I increase the priority to 1000.
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 1000, 1);
I tried priority values of 10,99 and 999 but the price and total in my cart did not change (even though I was able to confirm with get_price() that set_price() had actually set the price of the item.
I have a custom hook that adds a fee to my cart and I'm using a 3rd party plugin that adds product attributes. I suspect that these WooCommerce "add-ons" introduce delays that require me to delay my custom action.
I need to add a suffix text to the price of a woocommerce product while on WooCommerce cart.
Based on How to add suffix text to price in WooCommerce cart and checkout page? answer, so I'm trying to adapt that code to recognize product categories.
I am also using has_product_categories() custom conditional function from this answer.
Here is my code:
add_filter( 'woocommerce_cart_item_price', 'kd_custom_price_message' );
add_filter( 'woocommerce_cart_item_subtotal', 'kd_custom_price_message' );
add_filter( 'woocommerce_cart_subtotal', 'kd_custom_price_message' );
add_filter( 'woocommerce_cart_total', 'kd_custom_price_message' );
function kd_custom_price_message( $price ) {
if( is_cart() && has_product_categories( '46' ) ){
$afterPriceSymbol = ' Monthly';
return $price . $afterPriceSymbol;
} else {
return $price;
}
}
Sadly I keep getting the following error:
Fatal error: Uncaught ArgumentCountError: Too few arguments to function has_product_categories()
I haven't been able to either combine the two (as in including the suffix one here) or adapt this one to the suffix text one.
Any clue what I'm missing?
I have a function in my themes functions.php file which displays some information about the product. On the checkout page below the billing address I want to out put the information there.
Here is my function in the themes functions.php
function wc_checkout_description_so_1( $other_data, $cart_item )
{
$post_data = get_post( $cart_item['product_id'] );
echo '<div>HTML OUTPUT HERE</div>';
}
I have tried to use add_filter to below the billing address but doesnt not work:
add_filter( 'woocommerce_before_checkout_shipping_form', 'wc_checkout_description_so_1', 10, 2 );
All I need is the output below the shipping information and the above I think should work?
Thanks
J
woocommerce_after_checkout_shipping_form might be more appropriate for displaying something after the shipping address. Either way, the only variable that is passed to the woocommerce_after_checkout_shipping_form hook is the $checkout variable. You can var_dump that variable to see what it is available.
add_action( 'woocommerce_after_checkout_shipping_form', 'wc_checkout_description_so_1' );
function wc_checkout_description_so_1( $checkout )
{
var_dump( $checkout );
}
Im adding a custom item meta to every item with woocommerce_add_order_item_meta action.
I dont need to show this custom meta in the Order Detail, because it's an arry stringy that im using to print a pdf.
How can i remove this meta custom item? Is there some action to do it?
Thanks
I understand its a bit old question but I am answering for some other users who will have same issue in future.
If you want your order item meta to not display in admin order details page than you should append underscore (_) at the start of your meta name.
Example:
_custom_order_meta
The underscore trick no longer works. In Woo 3.x there is a hidden meta array:
add_filter('woocommerce_hidden_order_itemmeta',
array($this, 'hidden_order_itemmeta'), 50);
function hidden_order_itemmeta($args) {
$args[] = 'my_hidden_meta';
return $args;
}
It sounds like you need to keep it in order to print the PDF. If you override the order-details.php template you can possibly change:
$item_meta = new WC_Order_Item_Meta( $item['item_meta'], $_product );
to
$array = $item['item_meta'];
if( isset( $array['your_pdf_array_key'] ) ){ unset( $array['your_pdf_array_key'] ); }
$item_meta = new WC_Order_Item_Meta( $array, $_product );
EDIT
The wc_add_order_item_meta() function has 4 parameters as seen in the code:
function wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) {
return add_metadata( 'order_item', $item_id, $meta_key, $meta_value, $unique );
}
If you choose a $meta_key with a preceding underscore, the meta will be automatically hidden from view on the checkout/order-received page, the My Order's list of the My account area, as well as in the admin's order overview page.
Therefore, I would suggest making your woocommerce_add_order_item_meta callback function look something like the following:
add_action( 'woocommerce_add_order_item_meta', '25979024_add_order_item_meta', 10, 3 );
function 25979024_add_order_item_meta( $order_item_id, $cart_item, $cart_item_key ) {
wc_add_order_item_meta( $order_item_id, '_pdf_something', 'hide this stuff' );
}