I need functionality for "friend" customers, who can get products with better price. User role based solution is not what I'm looking for and customer wants it to work with coupons. They give coupon code to their customers and they get for example 8€ off from REGULAR price on certain products. The problem is, by default WooCommerce coupons calculate it from smallest price. If sale price is set, then this calculation is wrong and the customer gets it too cheap. Basically, I want coupon to give certain products fixed "friend" price.
I've been googling around and can't find a ready solution for it. Any suggestions how to solve this problem are welcome.
I have checked multiple plugins, but none of them has filled my requirements.
Add to functions.php. Based off of this code https://brilliantinfo.net/apply-coupon-discount-on-regular-price-in-woocommerce/
Modified for coupon type of fixed_product. If you need this to only work for a specific coupon then I can modify for that. (As it stands this will apply to any fixed_product coupons that are used)
add_action( 'woocommerce_before_calculate_totals', 'adjust_cart_coupon', 10, 1);
function adjust_cart_coupon( $cart_object) {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) ){
return;
}
$coupon = False;
if ($coupons = WC()->cart->get_applied_coupons() == False ) {
$coupon = False;
} else {
foreach ( WC()->cart->get_applied_coupons() as $code ) {
$coupons1 = new WC_Coupon( $code );
if ($coupons1->type == 'fixed_product'){
$coupon = True;
}
}
}
if ($coupon == True){
foreach ( $cart_object->get_cart() as $cart_item ){
$price = $cart_item['data']->regular_price;
//sets cart item to use regular price and not sale price
$cart_item['data']->set_price( $price );
}
}
}
The Discount Rules for WooCommerce plugin might fit your requirements.
With it you can apply a coupon, or any discount rule, to specific customers.
Also there is a setting to Apply discount based on Sale price or Regular price.
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 set the price of all related products on the products page to 10% less = 0.9
The goal is to provide a discount of all related products on the product page but when viewed as a product, give the normal price.
Overall, the idea is to provide incentive that generates up-selling of related products.
I am asking for two things here. ONE: change the product price for related products on the product page (10% off) and TWO: carry that discounted price into the cart and checkout when the related discounted product is added to cart from the product page.
I almost got the first part down, but the code I'm trying to get working is giving me an error saying:
Warning: A non-numeric value encountered
My code so far:
add_filter( 'woocommerce_get_price_html', 'related_product_price_discount', 100, 2 );
function related_product_price_discount( $price, $product ) {
global $woocommerce_loop;
// make sure this is a related product on product page
if( is_product() && $woocommerce_loop['name'] == 'related' ){
$price = $price * 0.9;
}
// return related product price with discount
return apply_filters( 'woocommerce_get_price', $price );
}
The rule in StackOverFlow is one question at the time, so I will answer only your first question, which is related to your code issue...
Note that the hook woocommerce_get_price_html is related to the displayed formatted price.
To avoid the error "Warning: A non-numeric value encountered", you will use the following:
add_filter( 'woocommerce_get_price_html', 'related_product_price_discount', 100, 2 );
function related_product_price_discount( $price_html, $product ) {
global $woocommerce_loop;
// make sure this is a related product on product page
if( is_product() && $woocommerce_loop['name'] == 'related' ){
$price_html = wc_price( wc_get_price_to_display( $product ) * 0.9 );
}
// return related product displayed discounted formatted price
return $price_html;
}
Code goes in functions.php file of your active child theme (active theme). Tested and works.
I want to remove the price range that is shown for variable products in the WooCommerce site I'm working on. On non-product pages I want to replace it with "from: [lowest price]" and on the product page I'd like to replace it simply with the price of the selected variation.
Any ideas how I can get it working that way?
Thanks,
Darren
The best possible way to do what you want is that you change it on non-product page and remove it from product page. On product page when you select a variaion, its price and remaining stock is shown below the dropdown. So there is no need for you to show it above. If you still want to do it you will need a js solution.
Try this, this is tested solution. I have commented the cases for better guidance and changing if you want.
function sr_change_variable_price($price, $product)
{
if ( $product->is_type( 'variable' ) && !is_product() )
{
return 'From: '.$product->get_variation_price( 'min' ); // if variable product and non-product page
} else if ( $product->is_type( 'variable' ) && is_product() )
{
return ''; // if variable product and product page
} else
{
return $price; // other cases
}
}
add_filter( 'woocommerce_get_price_html', 'sr_change_variable_price', 10, 2 );
I have a WooCommerce online shop that offers shipping to most products. Some of the products are for local pickup. I've tried setting a class on shipping zones with cost equal to zero and assigning the class on the products. But so far, the checkout still displays the shipping cost. Is there any way where some products will not have a shipping cost?
If you are searching for plugin solution, try WooCommerce Conditional Shipping and Payments. By using this plugin, you could add restrictions on certain product or product categories.
You've might want to look into the woocommerce_package_rates filter, which allows you to filter the set of shipping options that are available to the customer. An example would be something like this:
<?php
// add this snippet to functions.php:
add_filter( 'woocommerce_package_rates', function ( $rates, $package ) {
// examine $package for products. this could be a whitelist of specific
// products that you wish to be treated in a special manner...
$special_ids = array( 1, 2, 3, 4, 5 );
$special_product_present = false;
foreach ( $package['contents'] as $line_item ) {
if ( in_array( $line_item['product_id'], $special_ids ) ) {
$special_product_present = true;
}
}
$rates = array_filter( $rates, function ( $r ) use ( $special_product_present ) {
// do some logic here to return true (for rates that you wish to be displayed), or false.
// example: only allow shipping methods that start with "local"
if ( $special_product_present ) {
return preg_match( '/^local/', strtolower( $r->label ) );
} else {
return true;
}
} );
return $rates;
}, 10, 2 );
This blog post here shows some variations on that idea using this hook, including how to customize the available rates based on shopping cart value, customer's country, number of items in the cart, etc. And here's the source code: https://github.com/woocommerce/woocommerce/blob/v2.2.3/includes/class-wc-shipping.php#L366
I am trying to sell self-built travel packages with woocommerce. So a visitor would choose a number of their preferred hotels, activities, and transport, then add them into the shopping cart.
The problem I am facing is that items (travel products) are added into the shopping cart in the sequence that they were added.
However, I would need the function that like this: either the admin or guest will be able to re-arrange the positions (sequence) these items appear in the cart. Maybe like a AJAX drag and drop function would be great.
Is there a way to do so?
Ps. I am not refering to changing the order products appear in catalog, that's easy with plugins.
Please give me some direction. Thank you.
I once considered re-ordering the items in the cart from my plugin, but ultimately decided it wasn't worth it for me. Here's what I was going to use:
add_action( 'woocommerce_cart_loaded_from_session', 'so_26640996_reorder_cart_keys' );
/**
* Re-order the cart keys to keep container/bundled items from being separated in case of force-sells
* #param object $cart - the WC_Cart class
* #return void
*/
function so_26640996_reorder_cart_keys( $cart ){
if( $cart->cart_contents ) {
$new = array();
$contents = $cart->cart_contents;
// loop through the cart's contents
foreach( $cart->cart_contents as $cart_key => $cart_item ){
// add the item back into a new array of cart contents
$new[$cart_key]=$cart_item;
// if the cart item meets some condition re-arrange its position
if( isset( $cart_item['mnm_contents'] ) && is_array( $cart_item['mnm_contents'] ) ){
foreach($cart_item['mnm_contents'] as $key){
if( isset( $contents[$key] ) ){
$new[$key] = $contents[$key];
unset($contents[$key]);
}
}
}
}
$cart->cart_contents = $new;
}
}
It doesn't exactly fit your question (and is also very late) but maybe it will help someone with the same question.