Display the discount percentage on the sale badge and round it

180 Views Asked by At

so im having trouble with some code that displays sale badges on single product pages. The problem is that the badge shows bad percentage, we need to to round it to exact number... Now its showing 40.2% sale... We need it to show 40% sale.

Site with the product that shows 40.2% sale(just select the 18.7 option): https://juvelyrine.lt/produktas/ranku-darbo-minimalistinis-auksinis-ziedas-18-d/

The code:

// For simple products
add_filter( 'woocommerce_get_price_html', 'change_displayed_sale_price_html', 10, 2 );
function change_displayed_sale_price_html( $price, $product ) {
     // Only on sale products on frontend and excluding min/max price on variable products
    if( $product->is_on_sale() && ! is_admin() && $product->is_type('simple') ){
         // Get product prices
         $regular_price = (float) $product->get_regular_price(); // Regular price
         $sale_price = (float) $product->get_price(); // Active price (the "Sale price" when on-sale)

         // "Saving Percentage" calculation and formatting
         $precision = 0; // Max number of decimals
         $saving_percentage = round( 100 - ( $sale_price / $regular_price * 100 ), $precision ) . '%';

         // Append to the formated html price
         //$price .= sprintf( __('<p class="nuolaida">%s</p>', 'woocommerce' ), $saving_percentage );
         $price .= sprintf( __('<ins>' . $formatted_sale_price .'<p class="nuolaida">%s</p></ins>', 'woocommerce' ), $saving_percentage );
         
        //echo '<del>' . $formatted_regular_price . '</del> <ins>' . $formatted_sale_price .'<div class="nuolaida">' . $percentage_txt . '</div></ins>';
    }
    return $price;
}

// For product variations
add_filter( 'woocommerce_available_variation', 'custom_variation_price_saving_percentage', 10, 3 );
function custom_variation_price_saving_percentage( $data, $product, $variation ) {
    $active_price  = $data['display_price'];
    $regular_price = $data['display_regular_price'];

    if( $active_price !== $regular_price ) {
        $saving_percentage = round( 100 - ( $active_price / $regular_price * 100 ), 1 ) . '%';
        $data['price_html'] .= sprintf( __('<p class="nuolaida2">%s</p>', 'woocommerce' ), $saving_percentage );
    }
    return $data;
    
    
    
    
    function juvelyrine_meta_viewport() {
    echo '<!--<meta name="viewport" content="width=device-width, initial-scale=1">-->';
    }
    add_action( 'wp_head', 'juvelyrine_meta_viewport', 1 );
}


add_filter( 'woocommerce_sale_flash', 'add_percentage_to_sale_badge', 20, 3 );
function add_percentage_to_sale_badge( $html, $post, $product ) {

  if( $product->is_type('variable')){
      $percentages = array();

      // 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[] = ( floatval( $prices['regular_price'][ $key ] ) - floatval( $price ) ) / floatval( $prices['regular_price'][ $key ] ) * 100;
          }
      }
      // We keep the highest value
      $percentage = max($percentages) . '%';

  } elseif( $product->is_type('grouped') ){
      $percentages = array();

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

      // Loop through variation prices
      foreach( $children_ids as $child_id ){
          $child_product = wc_get_product($child_id);

          $regular_price = (float) $child_product->get_regular_price();
          $sale_price    = (float) $child_product->get_sale_price();

          if ( $sale_price != 0 || ! empty($sale_price) ) {
              // Calculate and set in the array the percentage for each child on sale
              $percentages[] = round(100 - ($sale_price / $regular_price * 100));
          }
      }
      // We keep the highest value
      $percentage = max($percentages) . '%';

  } else {
      $regular_price = (float) $product->get_regular_price();
      $sale_price    = (float) $product->get_sale_price();

      if ( $sale_price != 0 || ! empty($sale_price) ) {
          $percentage    = round(100 - ($sale_price / $regular_price * 100)) . '%';
      } else {
          return $html;
      }
  }
  return '<span class="onsale">' . esc_html__( 'SALE', 'woocommerce' ) . ' ' . $percentage . '</span>';
}

For me it looks like the code should round it, but it just does not...

1

There are 1 best solutions below

0
LoicTheAztec On

There are some mistakes and missing things in your code. Here is your revisited code that will display the rounded saving percentage

  • appended to the price (simple products and product variations)
  • on the sale badge for all product types.
// For simple products price
add_filter( 'woocommerce_get_price_html', 'onsale_simple_product_price_saving_percentage', 10, 2 );
function onsale_simple_product_price_saving_percentage( $price_html, $product ) {
    // Only on sale products on frontend and excluding min/max price on variable products
    if ($product->is_on_sale() && !is_admin() && $product->is_type('simple')) {
        // Get product prices to display
        $regular_price = (float) $product->get_regular_price(); // Regular price
        $active_price = (float) $product->get_price(); // Active price (the "Sale price" when on-sale)

        // "Saving Percentage" calculation and formatting
        $saving_percentage = round(100 - ($active_price / $regular_price * 100), 0) . '%';

        $price_html = str_replace('</ins>', '<p class="nuolaida">'.$saving_percentage.'</p></ins>', $price_html);
    }
    return $price_html;
}

// For product variations price
add_filter( 'woocommerce_available_variation', 'onsale_variation_price_saving_percentage', 10, 3 );
function onsale_variation_price_saving_percentage( $data, $product, $variation ) {
    // Only on sale variations
    if( ! $variation->is_on_sale() ) {
        return $data;
    }

    $saving_percentage = round( 100 - ( $data['display_price'] / $data['display_regular_price']* 100 ), 0 ) . '%';

    $data['price_html'] = str_replace('</ins>', '<p class="nuolaida">'.$saving_percentage.'</p></ins>', $data['price_html']);

    return $data;
}

// On sale badge with saving percentage, for simple, variable and grouped products
add_filter( 'woocommerce_sale_flash', 'add_saving_percentage_to_sale_badge', 20, 3 );
function add_saving_percentage_to_sale_badge( $html, $post, $product ) {
    $percentages = array(); // Initializing

    if ($product->is_type('variable')) {
        $prices      = $product->get_variation_prices();

        // Loop through variation prices
        foreach ( $prices['price'] as $key => $price ) {
            $regular_price = (float) $prices['regular_price'][$key];
            $active_price  = (float) $price;
            // Only on sale variations
            if ( $regular_price > $active_price )  {
                // Calculate and set in the array the percentage for each variation on sale
                $percentages[] = ( $regular_price - $active_price ) / $regular_price * 100;
            }
        }
        $percentage = round( max($percentages), 0 ) . '%'; // We keep the highest value  <===  Missing round()
    } 
    elseif ($product->is_type('grouped')) {
        // Get all children products
        $children_products  = array_filter( array_map( 'wc_get_product', $product->get_children() ), 'wc_products_array_filter_visible_grouped' );

        // Loop through children products
        foreach ($children_products as $child_product) {
            if( $child_product->is_on_sale() ) {
                $regular_price = (float) $child_product->get_regular_price();
                $active_price    = (float) $child_product->get_sale_price();
                $percentages[] = 100 - ($active_price / $regular_price * 100); // Add Calculated percentage to the array
            }
        }
        // We keep the highest value
        $percentage = round( max($percentages), 0 ) . '%';
    } else {
        $regular_price = (float) $product->get_regular_price();
        $sale_price    = (float) $product->get_sale_price();

        if ($sale_price != 0 || !empty($sale_price)) {
            $percentage    = round(100 - ($sale_price / $regular_price * 100)) . '%';
        } 
    }
    return sprintf('<span class="onsale">%s %s</span>', esc_html__('SALE', 'woocommerce'), $percentage );
}

It should work as expected