1
votes

I use some code that shows the discounted price on Woocommerce archive pages for on sale products:

add_filter( 'woocommerce_get_price_html', 'display_savings_as_price_and_percentage', 10, 2 );
//add_filter( 'woocommerce_variable_price_html','display_savings_as_price_and_percentage', 10, 2 );
function display_savings_as_price_and_percentage( $price, $product ) {

    if( $product->is_on_sale() && ! is_admin() && ! $product->is_type('variable')){
        $product_price = (float) $product->get_regular_price();
        $sale_price = (float) $product->get_price();
        $save_price = wc_price( $product_price - $sale_price );
        $save_percentage = round( 100 - ( $sale_price / $product_price * 100 ), 1 ) . '%';
        $price .= sprintf( __('<p class="saved-on-sale">Save: %s (%s)</p>', 'woocommerce' ), $save_price, $save_percentage );
    }
    return $price;
}

Discount on archives pages:

discount on archive

But it doesn't work for variable products and I've tried with every hook I've found but I cannot figure out how to make it work variable products. (I commented out the hook for the variable in my code).

This is what I would like to have:
If the variable has a price span of 10-20 with a discount making it 10-15 I would like for that to be displayed like this with the default price striked through:

  • $40 - $50
  • $20 - $30
  • Save: $20 (40-50%)

How can I replace the on sale product price for variable products with saving amount and percentages?

1

1 Answers

1
votes

The following code will handle both simple and variable on sale products:

add_filter( 'woocommerce_get_price_html', 'display_savings_price_and_percentages', 20, 2 );
function display_savings_price_and_percentages( $price_html, $product ) {
    // Only on frontend and for on sale products
    if( is_admin() || ! $product->is_on_sale() )
        return $price_html;

    // Only on archives pages
    if( ! ( is_shop() || is_product_category() || is_product_tag() ) )
        return $price_html;

    // Variable product type
    if( $product->is_type('variable')){
        $percentages = $savings = array(); // Initializing

        // Get all variation prices
        $prices = $product->get_variation_prices();

        // Loop through variation prices
        foreach( $prices['price'] as $key => $price ){
            // Only on sale variations
            if( $prices['regular_price'][$key] !== $price ){
                // Calculate and set in the array the percentage for each variation on sale
                $percentages[] = round(100 - ($prices['sale_price'][$key] / $prices['regular_price'][$key] * 100), 1 );
                // Calculate and set in the array the savings for each variation on sale
                $savings[]     = $prices['regular_price'][$key] - $prices['sale_price'][$key];
            }
        }

        $save_price      = wc_price( max($savings) );

        if( min($percentages) !== max($percentages) ){
            $save_percentage = min($percentages) . '-' . max($percentages) . '%';
            $save_text       = __( 'Save up to:', 'woocommerce' );
        } else {
            $save_percentage = max($percentages) . '%';
            $save_text       = __( 'Save:', 'woocommerce' );
        }
    }
    // All other product types
    else {
        $regular_price   = $product->get_regular_price();
        $sale_price      = $product->get_sale_price();
        $save_price      = wc_price( $regular_price - $sale_price );
        $save_percentage = round( 100 - ( $sale_price / $regular_price * 100 ), 1 ) . '%';
        $save_text       = __( 'Save:', 'woocommerce' );
    }

    return '<p class="saved-on-sale">' . sprintf( '%s %s (%s)', $save_text, $save_price, $save_percentage ) . '</p>';
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

enter image description here