Search code examples
phpwordpresswoocommercecartdiscount

Discount based on WooCommerce product custom input fields


I'm trying to give the user a discount based on a quantity field in the single product page.

Basically, the website sells tickets and I have a different price for adults and for children. So I created input fields in the single product page so the user would type how many adults and how many children he is buying for.

In the product admin I have a ACF (advanced custom field) for "children discount", so in the cart I want to give this discount based on the amount of children. For example, let's say that for this product the user is buying 5 tickets, 3 for adults and 2 for children, I want to calculate a discount for these 2 children.

What I've tried so far:

add_action( 'woocommerce_before_add_to_cart_button', 'custom_product_price_field', 5 );

function custom_product_price_field(){

    echo '<div class="custom-text text">
              <p>Quantity of adults:</p>
              <input type="text" name="qtty_adults" value="" title="Quantity Adults" class="qtty-field">
          </div>
          <div class="custom-text text">
              <p>Quantity of children:</p>
              <input type="text" name="qtty_kids" value="" title="Quantity Kids" class="qtty-field">
          </div>';

}


add_action('woocommerce_cart_calculate_fees' , 'add_user_discounts');

function add_user_discounts( WC_Cart $cart ){

    global $product;

    $qtty_kids = (float) sanitize_text_field( $_POST['qtty_kids'] );
    $discount_per_kid = (float) get_field('children_discount', $product->id);


    $discount = $qtty_kids * $discount_per_kid;

    $cart->add_fee( 'Discount for children', -$discount);
}

Doing this the discount is always $0

Can anyone give me some help on how to make this happen?


Solution

  • Your code is a bit outdated, with some mistakes and there is a lot of missing things to get what you expect…

    Try the following instead (updated):

    add_action( 'woocommerce_before_add_to_cart_button', 'custom_product_price_field', 5 );
    function custom_product_price_field(){
    
        echo '<div class="custom-text text">
            <p>'.__("Quantity of adults:").'</p>
            <input type="text" name="qtty_adults" value="" title="'.__("Quantity Adults").'" class="qtty-field">
        </div>
        <div class="custom-text text">
            <p>'.__("Quantity of children:").'</p>
            <input type="text" name="qtty_kids" value="" title="'.__("Quantity Kids").'" class="qtty-field">
        </div>';
    }
    
    // Add selected add-on option as custom cart item data
    add_filter( 'woocommerce_add_cart_item_data', 'filter_add_cart_item_data_callback', 10, 3 );
    function filter_add_cart_item_data_callback( $cart_item_data, $product_id, $variation_id ) {
        if ( isset( $_POST['qtty_kids'] )  && $children_discount = get_field( 'children_discount', $product_id ) ) {
            $cart_item_data['children_discount'] = (float) $children_discount - (float) sanitize_text_field( $_POST['qtty_kids'] );
            $cart_item_data['unique_key']        = md5( microtime().rand() ); // Make each item unique
        }
        return $cart_item_data;
    }
    
    // Set a discount based a product custom field(s)
    add_action('woocommerce_cart_calculate_fees' , 'add_children_discount', 10, 1 );
    function add_children_discount( $cart ){
        if ( is_admin() && ! defined('DOING_AJAX') )
            return;
    
        if ( did_action('woocommerce_cart_calculate_fees') >= 2 )
            return;
    
        $discount = 0; // Initialising
    
        // Loop through cart items
        foreach ( $cart->get_cart() as $cart_item ) {
            if( isset( $cart_item['children_discount'] ) ) {
                $discount += $cart_item['children_discount'];
            }
        }
    
        if ( $discount > 0 )
            $cart->add_fee( __("Discount for children", "woocommerce"), -$discount );
    }
    

    Tested and works.


    Related:

    Cart item discount based on quantity in Woocommerce 3