Calcule métodos/tarifas de envío dentro de un pedido existente en WooCommerce

5 minutos de lectura

avatar de usuario
zen

Básicamente, estoy tratando de replicar la funcionalidad como en la página del carrito donde un usuario puede agregar su zip code y calcula las tarifas de envío disponibles, pero estoy tratando de hacerlo desde el back-end dentro de un pedido ya creado.

No pude encontrar una manera de hacerlo directamente desde WC_Order Por ejemplo, lo mejor que tengo es borrar la sesión del carrito, agregar todos los artículos dentro del pedido a la sesión del carrito y luego tratar de calcularlo.

Esto es lo que tengo hasta ahora. Siempre estoy atascado en cómo calcular las tarifas para todo el pedido.

$order_id       = isset($_POST['order_id'])?$_POST['order_id']:0;
$country        = isset($_POST['country'])?$_POST['country']:0;
$state          = isset($_POST['state'])?$_POST['state']:0;
$postcode       = isset($_POST['postcode'])?$_POST['postcode']:0;
$city           = isset($_POST['city'])?$_POST['country']:0;
$order          = wc_get_order( $order_id );
$order_items    = $order->get_items();

// Don't know if this would save country of logged in user, or only create a temporary guest user session which is what I'd need
if ( $country != '' ) {
    WC()->customer->set_billing_location( $country, $state, $postcode, $city );
    WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
} else {
    WC()->customer->set_billing_address_to_base();
    WC()->customer->set_shipping_address_to_base();
}

// Remove all current items from cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
    WC()->cart->empty_cart();
}

// Add all items from the order to the cart
foreach ($order_items as $order_item) {
    WC()->cart->add_to_cart($order_item['product_id'], $order_item['qty']);
}

$totals = WC()->shipping->get_packages();

// $totals returns rates but I believe it is per each "package". It's not a cumulative rate like the cart page shows.

  • Mira esto

    – muy solo

    19 de marzo de 2019 a las 18:31

Ok, gracias a @mujuonly, pude resolverlo.

Aquí le mostramos cómo obtener todas las tarifas de envío calculadas, de la misma manera que se muestra en la página del carrito.

// Post variables
$order_id   = isset($_POST['order_id'])?$_POST['order_id']:0;
$country    = isset($_POST['country'])?$_POST['country']:0;
$state      = isset($_POST['state'])?$_POST['state']:0;
$postcode   = isset($_POST['postcode'])?$_POST['postcode']:0;
$city       = isset($_POST['city'])?$_POST['city']:0;

// Order and order items
$order          = wc_get_order( $order_id );
$order_items    = $order->get_items();

// Reset shipping first
WC()->shipping()->reset_shipping();

// Set correct temporary location
if ( $country != '' ) {
    WC()->customer->set_billing_location( $country, $state, $postcode, $city );
    WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
} else {
    WC()->customer->set_billing_address_to_base();
    WC()->customer->set_shipping_address_to_base();
}

// Remove all current items from cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
    WC()->cart->empty_cart();
}

// Add all items to cart
foreach ($order_items as $order_item) {
    WC()->cart->add_to_cart($order_item['product_id'], $order_item['qty']);
}

// Calculate shipping
$packages = WC()->cart->get_shipping_packages();
$shipping = WC()->shipping->calculate_shipping($packages);
$available_methods = WC()->shipping->get_packages();

$available_methods[0]['rates'] tendrá todas las tarifas de envío que estén disponibles a esa ubicación para los productos dentro del pedido.

  • ¿Puedes enviar el código completo del carrito para esta solución?

    – upss1988

    22 de junio de 2020 a las 21:25

  • ¿Alguna posibilidad de que pueda compartir cómo implementó esto, para que otros puedan hacer lo mismo con su back-end de WC?

    – inspirado

    10 de abril de 2021 a las 4:39

  • @inspirednz se implementó como un complemento para administrar pedidos manuales en el back-end.

    – zen

    13 abr 2021 a las 15:28

Intenta usar:

// Calculate totals
WC()->cart->calculate_totals();
WC()->cart->calculate_shipping();

// Retrieve the shipping total
$shipping_total = WC()->cart->get_shipping_total();

La clase WC_Cart debe tener todos los métodos que necesitaría para recrear cualquier funcionalidad de carrito que pueda necesitar. Le sugiero que lea y se familiarice con la definición de clase aquí…

https://docs.woocommerce.com/wc-apidocs/class-WC_Cart.html

Nota: esta no es una respuesta, no puedo comentar, por lo tanto, estoy escribiendo aquí. En mi caso, hay un problema con la respuesta aceptada:

Si el cliente ya agregó algunos artículos en el carrito, se perderán debido a la siguiente línea de código:

WC()->cart->empty_cart()

y en su lugar, el carrito se llena con los artículos del pedido anterior.

Hasta ahora parece que usar el carrito es necesario para realizar correctamente el cálculo de los paquetes de envío. Si es así, ¿hay alguna manera de que pueda crear un clon del carrito actual y luego calcular los paquetes de envío? No quiero afectar el carrito original de mi cliente al hacer este cálculo.

  • Mi pregunta y respuesta se aplican al cálculo de los métodos de envío desde el back-end de WordPress. Como tal, por lo general solo lo haría el administrador o los miembros administradores y, en ese caso, no importaría vaciar el carrito porque no vaciaría el carrito de los usuarios cuyos métodos de envío está tratando de calcular. Vacía el carrito del usuario actualmente conectado. intentaría algo como $cart_contents = WC()->cart->get_cart_contents() después WC()->cart->empty_cart() y toda la otra lógica, y finalmente WC()->cart->set_cart_contents($cart_contents). No lo he probado.

    – zen

    12 de noviembre de 2019 a las 21:16

¿Ha sido útil esta solución?