Search code examples
phpwordpresswoocommerceproductcart

Change price from a product variantion if corresponding product variantion is in WooCommerce cart


I have a series of products that have a variant 'A' and a variant 'B'.

I would need to make sure that when the variant 'A' of a product is present in the cart the variant 'B' of the same product is discounted by 15%.

The variant to be discounted is always 'B' because 'A' would already be discounted.

I tried with this code but it only works for one product and I have several products, plus this code has a poblem, if I first enter the product 'B' and then the product 'A' the price of product 'B' is not recalculated.

function woo_in_cart( $disc_product_id ) {
    global $woocommerce;


    if ( ! isset( $disc_product_id ) ) {
    return false;
     }


foreach ( $woocommerce->cart->get_cart() as $cart_myitem ) {
    if ( $cart_myitem['variation_id'] === $disc_product_id ) {
        return true;
    } else {
        return false;
         }
    }
    }
add_action( 'woocommerce_before_calculate_totals', 'webroom_change_price_of_product' );

function webroom_change_price_of_product( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
         return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    $target_product_id = 3161; // PRODUCT ID TO DISCOUNT

    if(woo_in_cart(3162)!=0) {
         foreach ( $cart->get_cart() as $cart_item ) {
             if ( ($disc_product_id-1) == $cart_item['variation_id'] ){
                 // Set your price
                 $price =round($cart_item['data']->price*((100-15) / 100), 2);
        
                 $cart_item['data']->set_price( $price ); 
        
             }
    
        }
    }
}

Any help will be appreciated!


Solution

  • The first piece of code will ensure that an extra checkbox appears for each variant.

    • The intention is that this is used with variable products that only contain 2 variants (A & B variant)
    • That the checkbox is checked for 1 of the 2 variants, which will stand for the 'A variant'
    // Add checkbox
    function action_woocommerce_variation_options( $loop, $variation_data, $variation ) {
        // Checkbox checked (ticked)
        $checked = get_post_meta( $variation->ID, '_mycheckbox', true ) == 'yes' ? 'checked' : '';
    
        // Output
        ?>
        <label class="tips" data-tip="<?php esc_attr_e( 'This is my data tip', 'woocommerce' ); ?>">
            <?php esc_html_e( 'This my checkbox:', 'woocommerce' ); ?>
            <input type="checkbox" class="checkbox variable_checkbox" name="variable_mycheckbox[<?php echo esc_attr( $loop ); ?>]"<?php echo $checked; ?>/>
        </label>
        <?php
    }
    add_action( 'woocommerce_variation_options', 'action_woocommerce_variation_options', 10, 3 );
    
    // Save checkbox
    function action_woocommerce_admin_process_variation_object( $variation, $i ) {
         // Isset, yes or no
        $value = isset( $_POST['variable_mycheckbox'][$i] ) ? 'yes' : 'no';
        
        // Update
        $variation->update_meta_data( '_mycheckbox', $value );
    }
    add_action( 'woocommerce_admin_process_variation_object', 'action_woocommerce_admin_process_variation_object', 10, 2 );
    

    checkbox variation options



    The 2nd piece of code will check if the checkbox is on for 1 of the 2 variants (The A variant)

    • If this is the case for the 'A variant', and the 'B variant' is in the shopping cart. Then a discount of 15% will be granted on the 'B variant'
    // Used to calculate totals
    function action_woocommerce_before_calculate_totals( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        // Discount in percent
        $discount = 15;
    
        // Iterating though each cart items
        foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
            // Only for variations
            if ( $cart_item['data']->get_type() == 'variation' ) {
                // Get the value of the checkbox
                $checked = $cart_item['data']->get_meta( '_mycheckbox' );
                
                // Variant is checked
                if ( $checked == 'yes' ) {              
                    // Get all variations ID of a variable product
                    // Main function for returning products
                    $variation = wc_get_product( $cart_item['product_id'] );
                    
                    // Get product child ids (Array)
                    $child_ids = $variation->get_children();
                    
                    // Normally there are 2 childsIDs, we will remove the current one so that the other variantionID is known
                    $other_variantion_id = array_diff( $child_ids, array( $cart_item['variation_id'] ) );
                    
                    // Convert to integer
                    $other_variantion_id = (int) reset( $other_variantion_id );
                    
                    // Call function - other product ID in cart? yes, then get that cart item
                    $other_cart_item = product_id_in_cart_get_cart_item( $other_variantion_id );
                    
                    // Finds whether a variable is an array
                    if ( is_array( $other_cart_item ) ) {                   
                        // Calculate new price
                        $new_price = round( $other_cart_item['data']->get_price() * ( ( 100 - $discount ) / 100 ), 2 );
                        
                        // Set price
                        $other_cart_item['data']->set_price( $new_price );
                    }
                }
            }
        }
    }
    add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
    
    // Product ID in cart? return cart_item
    function product_id_in_cart_get_cart_item( $product_id ) {  
        // Iterating though each cart items
        foreach( WC()->cart->get_cart() as $cart_item ) {
            // Compare
            if ( $product_id == $cart_item['data']->get_id() ) {
                // In cart
                return $cart_item;
            }
        }
        
        return false;
    }