Local Pickup fixed discount by product for specific products in WooCommerce

Viewed 160

In our shop, we want to offer our customers the option to pick up products. For products of type X, we want to give our customers a discount of 6€ on each of those products if they choose the pick-up option. To make it even more, complicated if they don't choose the pick-up option. The delivery fee which is 5,95 should not be applied to products of type X.

I tried to work with this piece of code but could not figure it out. It would be best if we could identify these products via their id and not their category

/**
* Discount for Local Pickup
*/
add_action( 'woocommerce_cart_calculate_fees', 'custom_discount_for_pickup_shipping_method', 10, 1 );
function custom_discount_for_pickup_shipping_method( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $discount_amount = 6; // Discount

    $chosen_shipping_method_id = WC()->session->get( 'chosen_shipping_methods' )[0];
    $chosen_shipping_method    = explode(':', $chosen_shipping_method_id)[0];
    

    // Only for Local pickup chosen shipping method
    if ( strpos( $chosen_shipping_method_id, 'local_pickup' ) !== false) {

        // Set variable
        $new_subtotal = 0;
        
        // Set discount excluded categories list
        $arr_discount_excluded_category = ['merch', 'rum'];

        // Set variable for matched excluded category from the cart list
        $arr_discount_excluded_category_matched = [];

        // Loop though each cart items and set prices in an array
        foreach ( $cart->get_cart() as $cart_item ) {

            // Get product
            $product = wc_get_product( $cart_item['product_id'] );

            // Get product category
            $category_list = wp_get_post_terms($cart_item['product_id'],'product_cat',array('fields'=>'names'));
            
            // Product has no discount
            $arr_discount_excluded_category_matched_by_item = array_intersect($category_list, $arr_discount_excluded_category);
            if ( ! $product->is_on_sale() && empty($arr_discount_excluded_category_matched_by_item)) {
                // line_subtotal
                $line_subtotal = $cart_item['line_subtotal'];

                // Add to new subtotal
                $new_subtotal += $line_subtotal;
            }
            else{
                $arr_discount_excluded_category_matched = array_merge($arr_discount_excluded_category_matched, $arr_discount_excluded_category_matched_by_item);
            }
        }
        
        // Calculate the discount
        $discount = 0;
        if($new_subtotal > 0){
            $discount = $new_subtotal - $discount_amount;
        }
        
        //Add notification
        if(!empty($arr_discount_excluded_category_matched)){
            $str_message = 'Pickup discount does not apply to products from the Category "' . implode('", "', array_unique($arr_discount_excluded_category_matched)) . '"';
            wc_add_notice($str_message, 'notice');
        }

        // Add the discount
        $cart->add_fee( __('Discount') . ' (' . $discount_amount . '€)', -$discount );
    }
}
1 Answers

The following will add a fixed discount by product only to specific defined products when Local Pickup shipping method is selected.

Define in the code below the desired product Ids and the discount amount by product:

add_action( 'woocommerce_cart_calculate_fees', 'fixed_discount_by_product_for_pickup_shipping_method', 10, 1 );
function fixed_discount_by_product_for_pickup_shipping_method( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $discount_by_product  = 6; // Here set the discount amount by product
    $targeted_product_ids = array(37,40); // Here set your excluded product ids

    $chosen_shipping_id = WC()->session->get('chosen_shipping_methods')[0];
    $total_discount     = 0; // Initializing

    // Only for "Local pickup" shipping method
    if ( strpos( $chosen_shipping_id, 'local_pickup' ) !== false ) {
        // Loop though each cart items and set prices in an array
        foreach ( $cart->get_cart() as $item ) {
            // Get matching targeted product ids from the current cart item
            $matched_product_ids = array_intersect( array($item['product_id'], $item['variation_id']), $targeted_product_ids);  
            
            // If product matches with targeted product Ids
            if ( ! empty($matched_product_ids) ) {
                // Add the discount by product
                $total_discount += $discount_by_product; 
            }
        }
        if ( $total_discount > 0 ) {
            $cart->add_fee( __('Local pickup discount'), -$total_discount ); // Add the discount
        }
    }
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.


To handle product quantity in the discount calculation, replace:

$total_discount += $discount_by_product;

with:

$total_discount += $discount_by_product * $item['quantity'];
Related