• Saltar a la navegación principal
  • Saltar al contenido principal
  • Saltar a la barra lateral principal

Dani Sánchez

  • ¿Eres agencia?
  • Quién soy
  • Servicios WordPress
    • Mantenimiento
    • Maquetación & Desarrollo
    • Soporte técnico
  • Portfolio
  • Blog
  • Presupuestos
Estás en: Inicio / Publicaciones / Excluir los productos virtuales del importe mínimo para activar el envío gratis en WooCommerce

Excluir los productos virtuales del importe mínimo para activar el envío gratis en WooCommerce

El 20 de mayo de 2021 por dani.sanchez Deja un comentario

En WooCommerce podemos fijar un importe mínimo de pedido para activar el Envío Gratuito, y que además, oculte el resto de métodos de envío cuando el gratuito está disponible, lo vimos en este post: WooCommerce – Activar el envío gratuito automático según el importe del carrito.

La cuestión es que los productos denominados virtuales, que no requieren de envío, sí cuentan para el importe mínimo que hace activar el Envío Gratuito. Esto ocasiona que si hemos establecido el importe mínimo en 50€, un cliente que compra un producto virtual valorado en 45€ y un producto físico valorado en 5€, ese producto físico sería enviado de forma gratuita según la configuración de WooCommerce.

Estuve buscando información al respecto y di con este post de 2017 en Stack Overflow: Exclude WooCommerce virtual product from counting towards free delivery

Un usuario compartió este filtro:

add_filter('woocommerce_package_rates', 'custom_free_shipping_option', 15, 2 );
function custom_free_shipping_option($rates, $package){

    // HERE set the "minimum order amount" for free shipping
    $limit = 50;

    $free_total = 0;

    // Get the cart content total excluding virtual products
    foreach( WC()->cart->get_cart() as $cart_item )
        if( ! $cart_item['data']->is_virtual( ) )
            $free_total += $cart_item['line_total'];

    // Set the cost to 0 based on specific cart content total
    if( $free_total > $limit )
        foreach ( $rates as $rate_key => $rate )
            if( 'pakkelabels_shipping_gls' === $rate->method_id )
                $rates[$rate->id]->cost = 0;

    return $rates;
}

Según el código, tenemos que especificar manualmente el límite de importe para que se active el Envío Gratuito, en la variable $limit. Seguramente habrá alguna forma de tomar dinámicamente el valor que hemos configurado en el método Envío Gratuito.

Probé este código en una instalación de pruebas y mi decepción es que parece no funcionar. Según el código, el producto Álbum no debería contar para el importe mínimo del Envío Gratuito, pero vemos que si cuenta.

Además tenemos el otro inconveniente que muestra tanto el envío gratuito como el envío de pago, cuando solo debería mostrar el Envío Gratuito si este está disponible.

Pero el código me dió una idea y lo adapte de la siguiente forma:

Primero, con el bucle Foreach, recorremos el carrito sumando el importe de los artículos, pero excluyendo aquellos que sean virtuales. El importe resultante se guarda en la variable $free_total. Hasta aquí, el ejemplo funciona perfecto.

// Get the cart content total excluding virtual products
    foreach( WC()->cart->get_cart() as $cart_item )
        if( ! $cart_item['data']->is_virtual( ) )
            $free_total += $cart_item['line_total'];

Ahora comprobamos si este importe es superior al importe mínimo establecido en la variable $limit, si se cumple, buscamos los métodos de envío hasta que coincida con el Envío Gratuito, cuando coincida paramos el bucle con break y este será el único a mostrar:

//If the total reaches the minimum order, only the free shipping is shown
    if( $free_total > $limit ){
        $free = array();
        foreach ( $rates as $rate_id => $rate ) {
            if ( 'free_shipping' === $rate->method_id ) {
                $free[ $rate_id ] = $rate;
                break;
            }
        }
        return ! empty( $free ) ? $free : $rates;

Y si no se cumple, es decir, si no llega al importe mínimo de pedido, recorremos los métodos de envío QUE NO SEAN el envío gratuito, para no mostrarlos como opción de envío:

}
    else{
        //If it does not reach the minimum order, the shipments that are NOT free are shown
        $free = array();
        foreach ( $rates as $rate_id => $rate ) {
            if ( 'free_shipping' != $rate->method_id ) {
                $free[ $rate_id ] = $rate;
            }
        }
        return ! empty( $free ) ? $free : $rates;   
    }

Aquí el codigo del snippet completo:

function custom_free_shipping_option($rates, $package){
    // HERE set the "minimum order amount" for free shipping
    $limit = 50;
    $free_total = 0;

    // Get the cart content total excluding virtual products
    foreach( WC()->cart->get_cart() as $cart_item )
        if( ! $cart_item['data']->is_virtual( ) )
            $free_total += $cart_item['line_total'];

    //If the total reaches the minimum order, only the free shipping is shown
    if( $free_total > $limit ){
        $free = array();
        foreach ( $rates as $rate_id => $rate ) {
            if ( 'free_shipping' === $rate->method_id ) {
                $free[ $rate_id ] = $rate;
                break;
            }
        }
        return ! empty( $free ) ? $free : $rates;   
    }
    else{
        //If it does not reach the minimum order, the shipments that are NOT free are shown
        $free = array();
        foreach ( $rates as $rate_id => $rate ) {
            if ( 'free_shipping' != $rate->method_id ) {
                $free[ $rate_id ] = $rate;
            }
        }
        return ! empty( $free ) ? $free : $rates;   
    }
}
add_filter('woocommerce_package_rates', 'custom_free_shipping_option', 15, 2 );

Ahora volvemos al ejemplo y comprobamos que funciona:

En este caso, el importe de los productos físicos no llega al mínimo de 50€ que haría saltar el Envío Gratuito, por lo que se cobran gastos de envío aunque el importe total sí supere los 50€.

Si añadimos más unidades del producto físico hasta superar la barrera de los 50€, ahora si salta el Envío Gratuito, y además se ocultan el resto de métodos de envío de pago:

En mi ejemplo solo tengo configurados 2 métodos de envío, el importe fijo de 5€ y el envío gratuito. No lo he probado con otros métodos de envío (combinando clases, etc). Pero en teoría debería funcionar correctamente.

Si tienes algún problema, déjamelo en la caja de comentarios.

Nos vemos en el siguiente post 😉

Publicado en: Publicaciones, Tutoriales, WooCommerce Etiquetado como: woocommerce

¿Quiéres invitarme a un café?

Si te has fijado en este blog no hay ni rastro de publicidad, todo el contenido publicado lo hago de forma artruista al igual que yo recurro a otros sitios cuando necesito algo. Pero si te he servido de ayuda y quieres agradecérmelo, puedes hacer una pequeña donación (el importe que quieras):

Entradas similares

  • Cerrar modales de Elementor con JavaScript (jQuery)
  • Redirección 301 para cambios de dominio
  • Guía rápida de Flexbox
  • Filtro de WooCommerce para personalizar el mensaje de «Gracias por tu pedido»
  • Portátiles reacondicionados, ¿mejor que uno nuevo?

Interacciones con los lectores

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Acepto la política de privacidad

Barra lateral principal

Autor

Dani Sánchez

logo mastodon @danisanchez

Entradas recientes

  • Iniciar sesión en nuestros VPS mediante SSH Keys
  • Cerrar modales de Elementor con JavaScript (jQuery)
  • Redirección 301 para cambios de dominio
  • Guía rápida de Flexbox
  • Filtro de WooCommerce para personalizar el mensaje de «Gracias por tu pedido»

Comentarios recientes

  1. Brandon Portes en Taller de verano de WooCommerce #1
  2. Sebastian en Instalar WordPress + MySQL + phpMyAdmin desde Docker Compose
  3. Rigol en Instalar LAMP (Linux, Apache, MySQL y PHP) en Fedora
  4. dani.sanchez en Instalar WordPress + MySQL + phpMyAdmin desde Docker Compose
  5. rikylinux en Instalar WordPress + MySQL + phpMyAdmin desde Docker Compose

Categorías

  • Actualidad
  • Afiliación AliExpress
  • Agent Press Pro
  • Bettaso Web Restaurantes
  • Cursos
  • Destacado
  • Divi
  • Drupal
  • Elementor
  • Genesis
  • Iniciación a PHP
  • Joomla!
  • Linux
  • Publicaciones
  • Tutoriales
  • WooCommerce
  • WordPress
Medium banner says Support Inkscape
Banner pie de página

Maquetación web, landings, blogs y tiendas online
cuidando hasta el mínimo detalle

Si necesitas que desarrolle tu proyecto web ponte en contacto conmigo.

Contacto
  • Mastodon
  • YouTube
  • LinkedIn

Alojado con energía 100% verde

Dani Sánchez © 2025 · Política de privacidad · Política de cookies