简体   繁体   中英

Set a min and max shipping rate cost by shipping zone in WooCommerce

I have currently 2 shipping zones (France, Europe) and each of them have several delivery option, including flat-rate. These flat-rate options have a different equation to calculate the fee based on item qty with AB and C three different shipping class. It easy enough to do with the advanced costs options native to Woocommerce.

My problem is that I would like to set a minimum and a maximum for the delivery fees, and these min / max are only for flat-rate option and different from a geographical zone to another. In a nutshell:

  • France flat-rate method: 2€ + (1€*[qtyA] + 2€*[qtyB] + 5€*[qtyC]) with Min = 7 and Max = 15
  • Europe flat-rate method: 6€ + (2€*[qtyA] + 4€*[qtyB] + 8€*[qtyC]) with Min = 10 and Max = 25

I have tried to write some code in function.php with conditions relying on the shipping zone and shipping method but neither my min or max are applied.

Hopefully maybe someone will be able to help as this is driving me nuts.

function maximum_shipping_rates_function( $rates, $package ) {

    $methods = WC()->shipping()->get_shipping_methods();
    $shipping_limit = 10.50; // I set my minimul to 10.50€
    $only_apply_to_rates = array( 'shipping_method_0_flat_rate2', 'flat_rate' ); // I put here the Shipping method ID thqt I get by inspecting the option on the checkout page

    // Loop through all rates
    foreach ( $rates as $rate_id => $rate ) {
        
        // Skip the shipping rates that are not in the list
        if ( ! in_array( $rate_id, $only_apply_to_rates ) ) {
            continue;
        }
        
        // Check if the rate is higher than my maximum
        if ( $rate->cost > $shipping_limit ) {
            $rate->cost = $shipping_limit;
            
            // Recalculate shipping taxes
            if ( $method = $methods[ $rate->get_method_id() ] ) {
                $taxes = WC_Tax::calc_shipping_tax( $rate->cost, WC_Tax::get_shipping_tax_rates() );
                $rate->set_taxes( $method->is_taxable() ? $taxes : array() );
            }
        }

    }

    return $rates;}
add_action( 'woocommerce_package_rates', 'maximum_shipping_rates_function', 10, 2 );

To set a different minimal and maximal shipping cost by shipping zone name, use following instead:

add_filter( 'woocommerce_package_rates', 'specificproductsshipping_methods', 10, 2 );
function specificproductsshipping_methods( $rates, $package ){
    $first_rate  = reset($rates); // get first rate (to get the shipping zone from)
    $chosen_zone = WC_Shipping_Zones::get_zone_by( 'instance_id', $first_rate->instance_id ); // Current Shipping Zone Object
    $zone_name   = $chosen_zone->get_zone_name(); // Get shipping zone name

    // Loop through all rates
    foreach ( $rates as $rate_key => $rate ) {
        // Targeting "Flat rate" shipping methods only
        if ( 'flat_rate' === $rate->method_id ) {
            $initial_cost = $new_cost = $rate->cost;

            // 1. For "France" shipping zone name (set min and max cost)
            if ( 'France' === $zone_name ) {
                if ( $initial_cost < 7 ) {
                    $new_cost = 7;
                } elseif ( $initial_cost > 15 ) {
                    $new_cost = 15;
                }
            }
            // For "Europe" shipping zone name (set min and max cost)
            elseif ( 'Europe' === $zone_name ) {
                if ( $initial_cost < 10 ) {
                    $new_cost = 10;
                } elseif ( $initial_cost > 25 ) {
                    $new_cost = 25;
                }
            }

            if ( $new_cost != $initial_cost ) {
                $rates[$rate_key]->cost = $new_cost; // Set the new cost

                $taxes = []; // Initializing

                // Taxes: Loop through the shipping taxes array (as they can be many)
                foreach ($rate->taxes as $key => $tax){
                    if( $tax > 0 ){
                        $initial_tax_cost = $tax; // Get the initial tax cost

                        $tax_rate    = $initial_tax_cost / $initial_cost; // Get the tax rate conversion

                        $taxes[$key] = $new_cost * $tax_rate; // Set the new tax cost in taxes costs array
                        $has_taxes   = true; // Enabling tax
                    }
                }
                if( isset($has_taxes) && $has_taxes ) {
                    $rates[$rate_key]->taxes = $taxes; // Set taxes costs array
                }
            }
        }
    }
    return $rates;
}

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

Don't forget to empty your cart to refresh shipping method caches.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM