1

I've been trying to implement a discount in my store with the following code:

add_action('woocommerce_before_calculate_totals', 'set_discount', 10 );

function set_discount( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;
    // Loop Through cart items
    foreach ( $cart->get_cart() as $cart_item ) {
        // 50% items discount
        $cart_item['data']->set_price( $cart_item['data']->get_price() / 2 ); 
    }
}
  • The code works on the cart page, the discount is applied as it should
  • The code works on the checkout page for a second or two, BUT when then the loading spinner has finalized the discount disappears and the original price is shown

It seems the set price is overwritten in the checkout by some standard AJAX request which reuses the original price, or something. I have tried using add_fee() with the same result, I have also tried deactivating all plugins (except woocommerce, of course) and I have tried switching to another theme - nothing works!

Using Wordpress 5.0.3, Woocommerce 3.5.4, Child theme of Storefront 2.4.2


UPDATE: Added screenshots.

1) This is what should be shown on checkout, and is being shown for around 1-2 seconds:

SCREENSHOT 1


2) This is what is shown once the loading spinner is finalized - the original prices:

SCREENSHOT 2

Community
  • 1
  • 1
erki
  • 25
  • 7
  • Need on discount on total? – Vasim Shaikh Feb 04 '19 at 11:24
  • I need discount on every cart item. The reason I want it on every cart item and not the total is because I want to implement some more complex logic in the discount once I get the example above to work. – erki Feb 04 '19 at 11:42

2 Answers2

1

The correct code to be used since Woocommerce 3.2+ avoiding problems and errors is:

add_action('woocommerce_before_calculate_totals', 'cart_item_discount', 10, 1 );
function cart_item_discount( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // Avoiding hook repetition (when using price calculations for example)
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // Loop Through cart items
    foreach ( $cart->get_cart() as $cart_item ) {

        $original_price   = $cart_item['data']->get_price(); // Get original product price
        $discounted_price = $original_price / 2; // 50 % of discount
        $cart_item['data']->set_price( $discounted_price );
    }
}

Code goes in function.php file of your active child theme (or active theme). Tested and works (Tested on last versions: Wordpress 5.0.x | Woocommerce 3.5.x | Storefront 2.4.x)

If it doesn't work, it's because some other things or customizations are interacting with it. You need first to check Woocommerce > Status for red items (where all overridden templates, at the end, need to be up to date).

See: Change cart item prices in Woocommerce 3

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Thank you for your suggestion. However, the problem that the price is reset in checkout still persists. I have checked and there's no overridden templates. I have also updated my PHP version to 7.2.10 per the recommendation on the very same page. And like I wrote before - nothing is active except woocommerce, and using Storefront theme. The products I'm selling are variable products, would that make any difference to your code? – erki Feb 04 '19 at 13:08
  • And for sure, the code is in functions.php in my active child theme. – erki Feb 04 '19 at 13:17
  • @Erik The problem you describe doesn't exist with the provided code, so it's something related to you… – LoicTheAztec Feb 04 '19 at 13:33
  • That is very odd. I just updated my virtual server environment (MAMP), I then installed a fresh wordpress instance with a completely new database, set up the child theme (using the standard twenty-nineteen), using a simple product with no variation - and I still experience the exact same issue. Do you have any idea where I can continue to look for the issue? Thank you very much. – erki Feb 04 '19 at 13:56
  • @Erik As a Woocommerce developer, I never use local server for development since few years now… I always use real servers to avoid all kind of problems. – LoicTheAztec Feb 04 '19 at 14:01
  • OK, I will try to implement the code on my staging server and see if that solves the issue, thanks for the advice. – erki Feb 04 '19 at 14:13
  • Just tried deploying to a real server, but the problem is still there. I just can't figure out what the difference is between my setup and yours/everyone elses. – erki Feb 04 '19 at 15:30
  • I finally figured out the problem. Seems I have had a mistake in my code for a very long time. In my child theme's functions.php i was including additional php files within the same function where I enqueued my parent theme's style.css. Moving the code outside of this function resolved the issue. Thank you! – erki Apr 26 '19 at 10:28
0
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price' );

function add_custom_price( $cart_object ) {
    $custom_price = 10; // This will be your custome price  
    foreach ( $cart_object->cart_contents as $key => $value ) {
        $custom_price = ($value['data']->price)/2;
        //$value['data']->price = $custom_price;
        // for WooCommerce version 3+ use: 
         $value['data']->set_price($custom_price);
    }
}
Vasim Shaikh
  • 4,485
  • 2
  • 23
  • 52