Detalles del pedido del cliente de WooCommerce en BS Modal

9 minutos de lectura

avatar de usuario
Yuri

En un sitio web de WordPress que ejecuta WooCommerce, el usuario puede iniciar sesión en su área personal (predeterminada) y mostrar información como:

  • historial de pedidos
  • Descargar
  • direcciones
  • Editar información
  • Cerrar sesión

En el orders pestaña, se presenta una tabla por defecto, que muestra una lista de todos los pedidos, con un View botón que redirige a la página de detalles completos de ese pedido.

Lo que intento hacer es mostrar esa vista de tabla en una ventana modal.

No tengo ningún problema en mostrar el modal con la URL de destino cargada en él. El verdadero problema es que la URL de destino es la de la página completa que se muestra como en un <iframe>y no es lo que quiero.

Creo que hay algún código abreviado que permite cargar solo esa tabla, o tal vez alguna función de woocommerce como load_order_content_by_id($id)?

¿Alguien puede señalarme en la dirección correcta?

Gracias

===RESUELTO===

Gracias a Raunak Gupta por señalarme la función correcta. Anulé la plantilla orders.php, agregué la ventana Modal html y edité $actions:

'view'   => array(
    'url'  => 'javascript:;',
    'data' => [
        'order-number' => $order->get_order_number()
    ],
    'name' => __( 'View', 'woocommerce' )
),

y en el mismo archivo:

foreach ( $actions as $key => $action ) {
    echo '<a href="' . esc_url( $action['url'] ) . '" class="button ' . sanitize_html_class( $key ) . '"';
    if(isset($action['data']) && is_array($action['data'])){
        foreach($action['data'] AS $data_attr=>$data_value){
            echo 'data-' . sanitize_html_class($data_attr) .'="' .esc_html($data_value) . '" ';
        }
    }
    echo '>' . esc_html( $action['name'] ) . '</a>';
}

un poco de js

$('.woocommerce-MyAccount-orders .button.view').on('click', function(e){
    e.preventDefault();
    var data = {};
    data.action = 'modal_order';
    data.order_number = $(this).data('order-number');

    $.get( ajax_script.ajax_url, data, function(response) {
        $('#modalOrderDetail').modal('show').find('.modal-body').html(response);
    });
});

y enganchado a wordpress por function.php

function modal_order() {
    if(is_user_logged_in()) {
        $order_number = $_GET['order_number'];
        woocommerce_order_details_table($order_number);
    }
}

add_action('wp_ajax_modal_order', 'modal_order');
add_action('wp_ajax_nopriv_modal_order', 'modal_order');

  • No sé woocommerce, pero tu pregunta parece muy vaga. Trate de agregar más detalles (tal vez un https://jsfiddle.net/ ) y es posible que obtenga más respuesta.

    – Rubén Pirotte

    26 de agosto de 2016 a las 7:15

  • Haría un violín si solo fuera posible cargar wordpress en él 🙂 Intentaré aclarar mi publicación

    – Yuri

    26 ago 2016 a las 11:30

  • Si alguien siente la necesidad de votar negativamente, al menos, agregue una explicación para ello.

    – Yuri

    5 de octubre de 2016 a las 8:18

  • @Yuri parece que creaste un agujero de seguridad en tu sitio si usaste ese código. Su functions.php solo cheques is_user_logged_in() no si el usuario posee ese pedido. Esto significa que cualquier ID de pedido que se solicite se mostrará siempre que el usuario haya iniciado sesión, incluidos los pedidos de otros usuarios. Mirando el código no parece hacer ninguna otra verificación de permisos.

    – rtpHarry

    11 de diciembre de 2019 a las 11:20

  • @Yuri también, no necesitas agregar una acción para wp_ajax_nopriv_modal_order porque esto es para solicitudes ajax de usuarios que no han iniciado sesión.

    – rtpHarry

    11 de diciembre de 2019 a las 11:21

avatar de usuario
LoicTheAztec

Aquí está el código completo para mostrar los pedidos actuales de los clientes en una ventana modal. Se basa en una consulta clásica para obtener pedidos de usuarios actuales y en la plantilla my-account/orders.php (ligeramente personalizado)

<?php

if(is_user_logged_in()):

    // The query
    $args = array(
        // WC orders post type
        'post_type'   => 'shop_order',
        'numberposts' => -1,
        // for current user id
        'meta_key'    => '_customer_user',
        'meta_value'  => get_current_user_id(),
        // get orders statuses
        'post_status' => array_keys(wc_get_order_statuses()),
    );

    // Get all customer orders
    $customer_orders = get_posts( $args );
    $count_ord = 0;
    if (!empty($customer_orders))
        foreach ( $customer_orders as $custo_order )
            $count_ord++;

    if ( $count_ord > 0 )
        $has_orders = true;
    else
        $has_orders = false;

    // the template my-account/orders.php  ?>

    <?php do_action( 'woocommerce_before_account_orders', $has_orders ); ?>

    <?php if ( $has_orders ) : ?>

    <table class="woocommerce-MyAccount-orders shop_table shop_table_responsive my_account_orders account-orders-table">
        <thead>
            <tr>
                <?php foreach ( wc_get_account_orders_columns() as $column_id => $column_name ) : ?>
                    <th class="<?php echo esc_attr( $column_id ); ?>"><span class="nobr"><?php echo esc_html( $column_name ); ?></span></th>
                <?php endforeach; ?>
            </tr>
        </thead>

        <tbody>
            <?php foreach ( $customer_orders as $customer_order ) :
                $order      = wc_get_order( $customer_order );
                $item_count = $order->get_item_count();
                ?>
                <tr class="order">
                    <?php foreach ( wc_get_account_orders_columns() as $column_id => $column_name ) : ?>
                        <td class="<?php echo esc_attr( $column_id ); ?>" data-title="<?php echo esc_attr( $column_name ); ?>">
                            <?php if ( has_action( 'woocommerce_my_account_my_orders_column_' . $column_id ) ) : ?>
                                <?php do_action( 'woocommerce_my_account_my_orders_column_' . $column_id, $order ); ?>

                            <?php elseif ( 'order-number' === $column_id ) : ?>
                                <a href="https://stackoverflow.com/questions/39070007/<?php echo esc_url( $order->get_view_order_url() ); ?>">
                                    <?php echo _x( '#', 'hash before order number', 'woocommerce' ) . $order->get_order_number(); ?>
                                </a>

                            <?php elseif ( 'order-date' === $column_id ) : ?>
                                <time datetime="<?php echo date( 'Y-m-d', strtotime( $order->order_date ) ); ?>" title="<?php echo esc_attr( strtotime( $order->order_date ) ); ?>"><?php echo date_i18n( get_option( 'date_format' ), strtotime( $order->order_date ) ); ?></time>

                            <?php elseif ( 'order-status' === $column_id ) : ?>
                                <?php echo wc_get_order_status_name( $order->get_status() ); ?>

                            <?php elseif ( 'order-total' === $column_id ) : ?>
                                <?php echo sprintf( _n( '%s for %s item', '%s for %s items', $item_count, 'woocommerce' ), $order->get_formatted_order_total(), $item_count ); ?>

                            <?php elseif ( 'order-actions' === $column_id ) : ?>
                                <?php
                                    $actions = array(
                                        'pay'    => array(
                                            'url'  => $order->get_checkout_payment_url(),
                                            'name' => __( 'Pay', 'woocommerce' )
                                        ),
                                        'view'   => array(
                                            'url'  => $order->get_view_order_url(),
                                            'name' => __( 'View', 'woocommerce' )
                                        ),
                                        'cancel' => array(
                                            'url'  => $order->get_cancel_order_url( wc_get_page_permalink( 'myaccount' ) ),
                                            'name' => __( 'Cancel', 'woocommerce' )
                                        )
                                    );

                                    if ( ! $order->needs_payment() ) {
                                        unset( $actions['pay'] );
                                    }

                                    if ( ! in_array( $order->get_status(), apply_filters( 'woocommerce_valid_order_statuses_for_cancel', array( 'pending', 'failed' ), $order ) ) ) {
                                        unset( $actions['cancel'] );
                                    }

                                    if ( $actions = apply_filters( 'woocommerce_my_account_my_orders_actions', $actions, $order ) ) {
                                        foreach ( $actions as $key => $action ) {
                                            echo '<a href="' . esc_url( $action['url'] ) . '" class="button ' . sanitize_html_class( $key ) . '">' . esc_html( $action['name'] ) . '</a>';
                                        }
                                    }
                                ?>
                            <?php endif; ?>
                        </td>
                    <?php endforeach; ?>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>

    <?php do_action( 'woocommerce_before_account_orders_pagination' ); ?>

    <?php if ( 1 < $customer_orders->max_num_pages ) : ?>
        <div class="woocommerce-Pagination">
            <?php if ( 1 !== $current_page ) : ?>
                <a class="woocommerce-Button woocommerce-Button--previous button" href="<?php echo esc_url( wc_get_endpoint_url( 'orders', $current_page - 1 ) ); ?>"><?php _e( 'Previous', 'woocommerce' ); ?></a>
            <?php endif; ?>

            <?php if ( $current_page !== intval( $customer_orders->max_num_pages ) ) : ?>
                <a class="woocommerce-Button woocommerce-Button--next button" href="<?php echo esc_url( wc_get_endpoint_url( 'orders', $current_page + 1 ) ); ?>"><?php _e( 'Next', 'woocommerce' ); ?></a>
            <?php endif; ?>
        </div>
    <?php endif; ?>

<?php else : ?>
    <div class="woocommerce-Message woocommerce-Message--info woocommerce-info">
        <a class="woocommerce-Button button" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>">
            <?php _e( 'Go Shop', 'woocommerce' ) ?>
        </a>
<?php endif; ?>
        <?php _e( 'No order has been made yet.', 'woocommerce' ); ?>
    </div>

<?php do_action( 'woocommerce_after_account_orders', $has_orders ); ?>

<?php endif; ?>

Tendrá que agregar reglas CSS existentes a su ventana modal y/o personalizar esas reglas CSS.

Este código está probado y es completamente funcional.

  • Gracias por la respuesta, pero con woocommerce_order_details_table( $order_id ) Pude obtener el resultado deseado con pocas líneas de código.

    – Yuri

    31 de agosto de 2016 a las 14:25

  • @Yuri Como realmente no lo mencionaste, tengo trabajo en esto, esa es la plantilla de woocommerce para pedidos de clientes actuales, con paginación y todo, como “mi cuenta” => “pedidos” (pero sin navegación, menú y todo lo que no quieres)… Esta es una solución completa llave en mano (alternativa).

    – LoicTheAztec

    31/08/2016 a las 14:30


  • Solo quería que la tabla de pedidos individuales se mostrara en una ventana Modal, no la lista completa de pedidos.

    – Yuri

    31 de agosto de 2016 a las 14:34

woocommerce_order_details_table ($order_id)

Esta función de WooCommerce devuelve los detalles completos del pedido en formato HTML por $order_id

  • Bonito 🙂 Y supongo que la plantilla que usa – order/order-details.php es anulable en un tema si la estructura no es la necesaria. +1

    – Guillermo Patton

    30 de agosto de 2016 a las 13:59

  • Sí, puedes anular order/order-details.php, order/order-details-item.php y order/order-details-customer.php archivos de acuerdo a su necesidad.

    – Raunak Gupta

    30 de agosto de 2016 a las 14:32

  • Además de anular la plantilla original, ¿qué variables globales debo incluir para usarla?

    – Yuri

    31 de agosto de 2016 a las 8:30

  • No tiene que escribir ninguna variable global ya que ya están presentes en esa plantilla, solo necesita copiarlas en su tema activo y personalizarlo en consecuencia. asumiendo que sabe a quién anular esa plantilla

    – Raunak Gupta

    31 de agosto de 2016 a las 8:39

No hay una sola función que yo sepa que pueda obtener todos los detalles del pedido que necesita de una sola vez, sin embargo, puede llamar WC_Order clase para obtener lo que necesita. Hacer algunas llamadas con métodos similares a estos le daría la información que necesita. Es probable que necesite hacer llamadas a algo más que al get_items() método dependiendo de la información exacta que necesita. Por lo general, devuelven objetos de estructura similar a los objetos de publicación.

$order = new WC_Order($post->ID);
$_order = $order->get_items();

Mire aquí en la sección ‘métodos heredados’ para encontrar los métodos a los que podría necesitar llamar para obtener toda la información que necesita. https://docs.woocommerce.com/wc-apidocs/class-WC_Order.html

¿Ha sido útil esta solución?