WooCommerce deposits: Keep only specific shipping methods for deposits

I use WooCommerce Deposits plugin and would like to hide all other shipping methods except “Local pickup” shipping method, if customer chooses to pay with a deposit.

Customer can choose on product page whether to pay with a deposit in example 10% or pay the full amount of the order. Shipping method flat_rate is used for sending orders (if they are paid in total) and should be hidden, because the customer needs to pay the remaining order amount first with local pick up in the (offline) store.

Choice on product page:

<input type="radio" name="wc_deposit_option" value="yes" id="wc-option-pay-deposit">
<input type="radio" name="wc_deposit_option" value="no" id="wc-option-pay-full" checked="checked">

I tried to combine the available hide shipping methods code snippets with _wc_deposit_enabled meta data, but I can’t figure it out. Help would be appreciated.

/**
     * Are deposits enabled for a specific product
     * @param  int $product_id
     * @return bool
     */
    public static function deposits_enabled( $product_id, $check_variations = true ) {
        $product = wc_get_product( $product_id );

        if ( ! $product || $product->is_type( array( 'grouped', 'external' ) ) ) {
            return false;
        }

        $setting = get_post_meta( $product_id, '_wc_deposit_enabled', true );

        if ( $check_variations && empty( $setting ) ) {
            $children = get_children( array(
                'post_parent' => $product_id,
                'post_type' => 'product_variation',
            ) );

            foreach ( $children as $child ) {
                $child_enabled = get_post_meta( $child->ID, '_wc_deposit_enabled', true );
                if ( $child_enabled ) {
                    $setting = $child_enabled;
                    break;
                }
            }
        }
        
        if ( empty( $setting ) ) {
            $setting = get_option( 'wc_deposits_default_enabled', 'no' );
        }

        if ( 'optional' === $setting || 'forced' === $setting ) {
            if ( 'plan' === self::get_deposit_type( $product_id ) && ! self::has_plans( $product_id ) ) {
                return false;
            }
            return true;
        }
        return false;
    }

Answer

The following code will only keep Local pickup shipping methods for deposits (for WooCommerce Deposits):

add_filter( 'woocommerce_package_rates', 'only_local_pickup_for_deposits', 100, 2 );
function only_local_pickup_for_deposits( $rates, $package ) {
    $has_deposit = false;

    // Loop through cart items for the current shipping package
    foreach( $package['contents'] as $item ) {
        if ( isset($item['is_deposit']) && $item['is_deposit'] ) {
            $has_deposit = true;
            break; // Stop the loop
        }
    }

    // If deposit is enabled for a cart item
    if( $has_deposit ) {
        // Loop through shipping rates
        foreach ( $rates as $rate_key => $rate ) {
            // Remove all shipping methods except "Local pickup" 
            if ( 'local_pickup' !== $rate->method_id ) {
                unset($rates[$rate_key]);
            }
        }
    }
    return $rates;
}

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

Leave a Reply

Your email address will not be published. Required fields are marked *