In my theme's functions.php file, I added the following code snippet, that adds a small discount based on quantity, for a specific product which name contains "Hydrogel".
However, it don't apply that discount on checkout, it still keeps the original product price.
Here is the code :
function display_quantity_discount_message() {
global $product;
// Check if the product name contains "Hydrogel"
if (strpos($product->get_name(), 'Hydrogel') !== false) {
// Define your quantity-based discounts here
$discounts = array(
2 => 60, // For 2 pieces, you pay 60 Lei
3 => 85, // For 3 pieces, you pay 55 Lei
// Add more quantities and discounts as needed
);
// Get the current quantity input field
echo '<div class="quantity-discount-message">';
echo '<p>Reducere:</p>';
echo '<ul>';
foreach ($discounts as $quantity => $price) {
echo '<li>';
echo '<input type="radio" name="quantity_discount" value="' . $quantity . '" data-price="' . $price . '"> ';
echo 'Cumpără <span style="color:green; font-weight:bold;">' . $quantity . '</span> pentru doar <span style="text-decoration: line-through; color:red; font-weight:bold;">' . ($quantity * $product->get_price()) . '</span> <span style="color:red; font-weight:bold;">' . $price . ' Lei</span>';
echo '</li>';
}
echo '</ul>';
echo '</div>';
// Enqueue JavaScript to update the price when a radio button is selected
wc_enqueue_js('
jQuery(document).ready(function($) {
$("input[name=\'quantity_discount\']").change(function() {
var selectedPrice = parseInt($(this).data("price"));
$("input[name=\'quantity\']").val($(this).val());
$(".single_add_to_cart_button").data("price", selectedPrice).attr("data-price", selectedPrice);
$(".single_add_to_cart_button").html("Adaugă în coș - " + selectedPrice + " Lei");
// Update the cart item price
if( selectedPrice > 0 ) {
var data = {
action: "update_cart_item_price",
price: selectedPrice
};
$.post(wc_cart_params.ajax_url, data, function(response) {
$("body").trigger("update_checkout");
});
}
});
});
');
}
}
// Hook the function to display the message below the "Add to Cart" button
add_action('woocommerce_before_add_to_cart_button', 'display_quantity_discount_message');
// Add an action to update cart item price
add_action('wp_ajax_update_cart_item_price', 'update_cart_item_price');
add_action('wp_ajax_nopriv_update_cart_item_price', 'update_cart_item_price');
function update_cart_item_price() {
if (isset($_POST['price'])) {
$new_price = floatval($_POST['price']);
WC()->cart->set_discount_total(0); // Remove any discounts to avoid conflicts
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
$cart_item['data']->set_price($new_price);
}
WC()->cart->calculate_totals();
echo json_encode(array('success' => true));
}
wp_die();
}
Update:
I wrote incorrectly the code block. Now everything is working fine except one thing: The total amount in "Total" is not calculated correctly. I think something is wrote incorrectly where $cart_item['data']->set_price($new_price);
is written.
You don't need Ajax here, as it's a quantity discount. I have revisited all your function, extracting your discount settings in its own function, and adding the necessary functions to update the product "Hydrogel" price based on the quantity.
I have lightly improved your jQuery code, so if you change the quantity it updates the price too and select/unselect the correct radio button.
The code:
// Define your quantity-based discounts below
function get_hydrogel_discounts() {
return array(
'product' => 'Hydrogel', // Product word to search
'discounts' => array(
2 => 60, // For 2 pieces, you pay 60 Lei
3 => 55, // For 3 pieces, you pay 55 Lei
)
);
}
// Add input radio buttons to the product (quantity discount)
add_action('woocommerce_before_add_to_cart_button', 'display_quantity_discount_message');
function display_quantity_discount_message() {
global $product;
$settings = get_hydrogel_discounts(); // Load discounts settings
// Check if the product name contains "Hydrogel"
if (strpos($product->get_name(), $settings['product']) !== false) {
echo '<div class="quantity-discount-message"><p>Reducere:</p><ul>';
foreach ($settings as $quantity => $price) {
printf('<li><input type="radio" name="quantity_discount" value="%s" data-price="%s"> Cumpără
<span style="color:green; font-weight:bold;">%s</span> pentru doar
<span style="text-decoration: line-through; color:red; font-weight:bold;">%s</span>
<span style="color:red; font-weight:bold;">%s Lei</span></li>',
$quantity, $price, $quantity, ($quantity * $product->get_price()), $price );
}
echo '</ul></div>';
// Enqueue JavaScript to update the price when a radio button is selected
// and when quatity is changed
wc_enqueue_js("const a = '.single_add_to_cart_button', b = $(a).html();
$('input[name=quantity_discount]').on('change', function(){
const selectedPrice = parseInt($(this).data('price'));
$('input[name=quantity]').val($(this).val());
$(a).data('price', selectedPrice).attr('data-price', selectedPrice);
$(a).html('Adaugă în coș - '+selectedPrice+' Lei');
});
$('input[name=quantity]').on('change input', function(){
if ( $(this).val() == 1 ) {
$('input[name=quantity_discount]').prop('checked', false);
$(a).html(b);
} else {
const v = $(this).val() == 0 ? 1 : $(this).val();
$('input[name=quantity_discount][value='+v+']').trigger('click');
}
});");
}
}
// For mini cart: Update the displayed price
add_action( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 2 );
function filter_cart_item_price( $price_html, $item ) {
global $product;
$settings = get_hydrogel_discounts(); // Load discounts settings
// Check if the product name contains "Hydrogel"
if (strpos($item['data']->get_name(), $settings['product']) !== false && $item['quantity'] > 1 ) {
if ( $item['quantity'] > 2 ) {
$args = array( 'price' => floatval( $settings['discounts'][3]) );
} elseif ( $item['quantity'] == 2 ) {
$args = array( 'price' => floatval( $settings['discounts'][2]) );
}
if ( WC()->cart->display_prices_including_tax() ) {
$product_price = wc_get_price_including_tax( $item['data'], $args );
} else {
$product_price = wc_get_price_excluding_tax( $item['data'], $args );
}
return wc_price( $product_price );
}
return $price_html;
}
// Update cart item price based on the selected quantity
add_action( 'woocommerce_before_calculate_totals', 'apply_cart_item_discounted_price', 100 );
function apply_cart_item_discounted_price( $cart ) {
if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$settings = get_hydrogel_discounts(); // Load discounts settings
// Loop through cart items
foreach ( $cart->get_cart() as $item ) {
// Check if the product name contains "Hydrogel"
if (strpos($item['data']->get_name(), $settings['product']) !== false) {
if ( $item['quantity'] > 2 ) {
$item['data']->set_price($settings['discounts'][3]); // Set the discounted price
} elseif ( $item['quantity'] == 2 ) {
$item['data']->set_price($settings['discounts'][2]); // Set the discounted price
}
}
}
}
Code goes in functions.php file of your child theme (or in a plugin). Tested and works.