This question already has an answer here:
What I would like to do is take the regular price for each of my Woocommerce products and dynamically create a sale price based on several conditions. This would include the following:
1) Showing the dynamically created sale price on the shop page products. 2) Sale price displayed in the cart (item price and total in cart are reflective of the dynamic sale price ) 3) Checkout page and totals reflect dynamic sale price.
Researching several solutions I came up with the following solution:
// Generating dynamically the product "regular price"
add_filter( 'woocommerce_product_get_regular_price',
'custom_dynamic_regular_price', 10, 2 );
add_filter( 'woocommerce_product_variation_get_regular_price',
'custom_dynamic_regular_price', 10, 2 );
function custom_dynamic_regular_price( $regular_price, $product ) {
if( empty($regular_price) || $regular_price == 0 )
return $product->get_price();
else
return $regular_price;
}
// Generating dynamically the product "sale price"
add_filter( 'woocommerce_product_get_sale_price',
'custom_dynamic_sale_price', 10, 2 );
add_filter( 'woocommerce_product_variation_get_sale_price',
'custom_dynamic_sale_price', 10, 2 );
function custom_dynamic_sale_price( $sale_price, $product ) {
$rate = 0.7;
if( empty($sale_price) || $sale_price == 0 )
return $product->get_regular_price() * $rate;
else
return $sale_price;
};
// Displayed formatted regular price + sale price
add_filter( 'woocommerce_get_price_html', 'custom_dynamic_sale_price_html',
20, 2 );
function custom_dynamic_sale_price_html( $price_html, $product ) {
if( $product->is_type('variable') ) return $price_html;
$price_html = wc_format_sale_price( wc_get_price_to_display( $product,
array( 'price' => $product->get_regular_price() ) ),
wc_get_price_to_display( $product, array( 'price' => $product-
>get_sale_price() ) ) ) . $product->get_price_suffix();
return $price_html;
}
add_action( 'woocommerce_before_calculate_totals',
'set_cart_item_sale_price', 10, 1 );
function set_cart_item_sale_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Iterate through each cart item
foreach( $cart->get_cart() as $cart_item ) {
$price = $cart_item['data']->get_sale_price(); // get sale price
$cart_item['data']->set_price( $price ); // Set the sale price
}
}
add_filter( 'woocommerce_cart_item_price',
'bbloomer_change_cart_table_price_display', 30, 3 );
function bbloomer_change_cart_table_price_display( $price, $values,
$cart_item_key ) {
$slashed_price = $values['data']->get_price_html();
$is_on_sale = $values['data']->is_on_sale();
if ( $is_on_sale ) {
$price = $slashed_price;
}
return $price;
}
This works except for the cart table total displays the original price totals, not the dynamic sale price totals. There must be an easier way of doing this. Any help would be appreciated. Thanks, Jules
Somehow, the discount was being applied twice. Perhaps it was theme or framework related, I am not sure. Adding one line in both functions restricting when the discount is applied made it work for me.