¿Cómo agregar funcionalidad para que los pedidos de woocommerce sean visibles para un rol de usuario de controlador en la misma ciudad?

14 minutos de lectura

Tengo una tienda Woo-commerce de WordPress con la versión Pro de los controladores de entrega para el complemento woo-commerce (https://wordpress.org/plugins/delivery-drivers-for-woocommerce/).

Todo funciona bien ya que cualquier usuario que tenga el rol de usuario: el ‘conductor de entrega’ puede ver y reclamar todos los pedidos que se procesan a través del sitio web, en este momento usando la configuración de zonas de entrega/envío de Woo-Commerce. Lo he configurado para que solo los clientes que residen en una determinada ciudad puede hacer un pedido y solo estoy aprobando repartidores en esa área.

Pero quiero implementar esto en otras ciudades, puedo agregar los códigos postales para que los usuarios puedan ordenar desde esos códigos postales, pero el problema es con el complemento de los conductores de entrega: los conductores verán todos los pedidos de todas las ciudades en su tablero. Solo quiero que los conductores vean y reclamen pedidos en la ciudad en la que residen (la ciudad a la que se han asignado).

Aquí está el código de la funcionalidad que muestra todos los pedidos realizados en el sitio web para el tipo de rol de usuario ‘conductor de entrega’:

driver-dashboard-shortcode.php

<?php
/**
* The Unclaimed Orders Shortcode.

**/

function ddwc_pro_dashboard_shortcode() {

// Check if user is logged in.
if ( is_user_logged_in() ) {
    // Get the user ID.
    $user_id = get_current_user_id();

    // Get the user object.
    $user_meta = get_userdata( $user_id );

    // If user_id doesn't equal zero.
    if ( 0 != $user_id ) {

        // If claim delivery button is pushed.
        if ( ! empty( $_GET['claim_delivery'] ) ) {

            // Get deliver ID to claim.
            $claim_delivery = $_GET['claim_delivery'];

            // Update order status.
            $order = wc_get_order( $claim_delivery );
            $order->update_status( 'driver-assigned' );

            // Update order with driver ID.
            update_post_meta( $claim_delivery, 'ddwc_driver_id', $user_id, -1 );

            // Redirect URL.
            $redirect_url = apply_filters( 'ddwc_pro_claim_order_redirect_url', get_permalink( get_option( 'woocommerce_myaccount_page_id' ) ) . '/driver-dashboard/?orderid=' . $claim_delivery, $claim_delivery );

            // Redirect driver to the order details.
            wp_redirect( $redirect_url );
        }

        // Get all the user roles as an array.
        $user_roles = $user_meta->roles;

        // Check if the role you're interested in, is present in the array.
        if ( in_array( 'driver', $user_roles, true ) ) {

            // Set variable for driver ID.
            if ( isset( $_GET['orderid'] ) && ( '' != $_GET['orderid'] ) ) {
                $driver_id = get_post_meta( $_GET['orderid'], 'ddwc_driver_id', true );
            }

            /**
             * Args for Orders with no driver ID attached.
             */
            $args = array(
                'post_type'      => 'shop_order',
                'posts_per_page' => -1,
                'post_status'    => 'any',
                'post_parent'    => 0
            );

            /**
             * Get Orders with Driver ID attached
             */
            $unclaimed_orders = get_posts( $args );

            /**
             * If there are orders to loop through.
             */
            if ( $unclaimed_orders ) {

                // Total for table thead.
                $total_title="<td>" . esc_attr__( 'Total', 'ddwc' ) . '</td>';

                do_action( 'ddwc_pro_unclaimed_orders_table_before' );

                echo '<table class="ddwc-dashboard">';
                echo '<thead><tr><td>' . esc_attr__( 'Date', 'ddwc-pro' ) . '</td><td>' . esc_attr__( 'Address', 'ddwc-pro' ) . '</td>' . apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_total_title', $total_title ) . '<td></td></tr></thead>';
                echo '<tbody>';

                do_action( 'ddwc_pro_unclaimed_orders_table_tbody_before' );

                foreach ( $unclaimed_orders as $driver_order ) {

                    // Get Driver ID (if set).
                    $driver_id_setting = get_post_meta( $driver_order->ID, 'ddwc_driver_id', TRUE );

                    // Get an instance of the WC_Order object.
                    $order = wc_get_order( $driver_order->ID );

                    // Get the required order data.
                    $order_data         = $order->get_data();
                    $currency_code      = $order_data['currency'];
                    $currency_symbol    = get_woocommerce_currency_symbol( $currency_code );
                    $order_id           = $order_data['id'];
                    $order_status       = $order_data['status'];
                    $order_date_created = $order_data['date_created']->date( 'm-d-Y' );

                    ## CART INFORMATION:

                    $order_total = $order_data['total'];

                    ## BILLING INFORMATION:

                    $order_billing_city     = $order_data['billing']['city'];
                    $order_billing_state    = $order_data['billing']['state'];
                    $order_billing_postcode = $order_data['billing']['postcode'];

                    ## SHIPPING INFORMATION:

                    $order_shipping_city     = $order_data['shipping']['city'];
                    $order_shipping_state    = $order_data['shipping']['state'];
                    $order_shipping_postcode = $order_data['shipping']['postcode'];

                    // Create address to use in the table.
                    $address = $order_billing_city . ' ' . $order_billing_state . ', ' . $order_billing_postcode;

                    // Set address to shipping (if available).
                    if ( isset( $order_shipping_city ) ) {
                        $address = $order_shipping_city . ' ' . $order_shipping_state . ', ' . $order_shipping_postcode;
                    }

                    // Allowed statuses.
                    $status_array = apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_status_array', array( 'processing' ) );

                    // Display unassigned orders.
                    if ( in_array( $order_status, $status_array ) && ( -1 == $driver_id_setting || '' === $driver_id_setting ) ) {
                        echo '<tr>';

                        echo '<td>' . $order_date_created . '</td>';
                        echo '<td>' . apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_table_address', $address ) . '</td>';

                        if ( isset( $order_total ) ) {
                            $order_total="<td>"  . $currency_symbol . $order_total . '</td>';
                            echo apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_total', $order_total );
                        } else {
                            echo '<td>-</td>';
                        }

                        echo '<td><a href="' . apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_button_url', '?claim_delivery=' . $order_id, $order_id ) . '" class="button">' . apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_button_text', __( 'CLAIM', 'ddwc-pro' ) ) . '</a></td>';

                        echo '</tr>';
                    } else {
                        // Do nothing.
                    }
                }

                do_action( 'ddwc_pro_unclaimed_orders_table_tbody_after' );

                echo '</tbody>';
                echo '</table>';

                do_action( 'ddwc_pro_unclaimed_orders_table_after' );

                // Driver dashboard button.
                $dashboard_button = '<a href="' . apply_filters( 'ddwc_pro_back_to_driver_dashboard_link', get_permalink( get_option( 'woocommerce_myaccount_page_id' ) ) . 'driver-dashboard/' ) . '">&larr; ' . __( 'Driver Dashboard', 'ddwc-pro' ) . '</a>';

                // Filter "Driver Dashboard" button.
                echo apply_filters( 'ddwc_pro_back_to_driver_dashboard_button', $dashboard_button );

            } else {

                do_action( 'ddwc_pro_assigned_orders_empty_before' );

                // Message - No assigned orders.
                $empty  = '<h3 class="ddwc assigned-orders">' . __( 'Assigned Orders', 'ddwc-pro' ) . '</h3>';
                $empty .= '<p>' . __( 'You do not have any assigned orders.', 'ddwc-pro' ) . '</p>';

                echo apply_filters( 'ddwc_pro_assigned_orders_empty', $empty );

                do_action( 'ddwc_pro_assigned_orders_empty_after' );

            }
        } else {

            // Set the Access Denied page text.
            $access_denied = '<h3 class="ddwc access-denied">' . __( 'Access Denied', 'ddwc-pro' ) . '</h3><p>' . __( 'Sorry, but you are not able to view this page.', 'ddwc-pro' ) . '</p>';

            // Filter Access Denied text.
            echo apply_filters( 'ddwc_access_denied', $access_denied );
        }

    } else {
        // Do nothing.
    }
} else {
    apply_filters( 'ddwc_pro_dashboard_login_form', wp_login_form() );
}
}
add_shortcode( 'ddwc_pro_dashboard', 'ddwc_pro_dashboard_shortcode' );

Había pensado en una forma de implementar esta funcionalidad: he creado un campo personalizado (solo para los conductores de entrega) en la sección de detalles de la cuenta de Woocommerce ‘mi cuenta/editar cuenta’. El campo es una lista desplegable de ciudades que un repartidor puede asignarse a sí mismo en los detalles de su cuenta.

Y quiero llamar a una función que verifique si la etiqueta de dirección de ‘pueblo/ciudad’ coincide con la ciudad seleccionada en el perfil de un conductor, si es así, entonces el conductor puede ver ese pedido (pedidos). Si un conductor no ha seleccionado una ciudad en ese menú desplegable, no verá ningún pedido.

Así es como he agregado la lista desplegable de ciudades:

  <?php

   /**
   * Get additional account fields.
   *
   * @return array
   */
   function iconic_get_account_fields() {
    return apply_filters( 'iconic_account_fields', array(
        'city_select'              => array(
           'type'                  => 'select',
           'label'                 => __( 'Select City', 'iconic' ),
           'hide_in_account'       => false,
            'hide_in_admin'        => false,
            'required'             => false,
           'options' => array(
               ''    => __( 'Select an option...', 'iconic' ),
               1     => __( 'Manchester', 'iconic' ),
               2     => __( 'Birmingham', 'iconic' ),
               3     => __( 'London', 'iconic' ),
           ),
        'bank_name'                 => array(
            'type'                 => 'text',
            'label'                => __( 'Bank Name', 'iconic' ),
            'hide_in_account'      => false,
            'hide_in_admin'        => false,
            'required'             => false,
        ),

    ) );
}

/**
 * Add post values to account fields if set.
 *
 * @param array $fields
 *
 * @return array
 */
function iconic_add_post_data_to_account_fields( $fields ) {
    if ( empty( $_POST ) ) {
        return $fields;
    }

    foreach ( $fields as $key => $field_args ) {
        if ( empty( $_POST[ $key ] ) ) {
            $fields[ $key ]['value'] = '';
            continue;
        }

        $fields[ $key ]['value'] = $_POST[ $key ];
    }

    return $fields;
}

add_filter( 'iconic_account_fields', 'iconic_add_post_data_to_account_fields', 10, 1 );

/**
 * Add field to account area.
 */
function iconic_print_user_frontend_fields() {
    $fields            = iconic_get_account_fields();
    $is_user_logged_in = is_user_logged_in();

    foreach ( $fields as $key => $field_args ) {
        $value = null;

        if ( ! iconic_is_field_visible( $field_args ) ) {
            continue;
        }

        if ( $is_user_logged_in ) {
            $user_id = iconic_get_edit_user_id();
            $value   = iconic_get_userdata( $user_id, $key );
        }

        $value = isset( $field_args['value'] ) ? $field_args['value'] : $value;

        woocommerce_form_field( $key, $field_args, $value );
    }
}
add_action( 'woocommerce_edit_account_form', 'iconic_print_user_frontend_fields', 10 ); // my account

/**
 * Get user data.
 *
 * @param $user_id
 * @param $key
 *
 * @return mixed|string
 */
function iconic_get_userdata( $user_id, $key ) {
    if ( ! iconic_is_userdata( $key ) ) {
        return get_user_meta( $user_id, $key, true );
    }

    $userdata = get_userdata( $user_id );

    if ( ! $userdata || ! isset( $userdata->{$key} ) ) {
        return '';
    }

    return $userdata->{$key};
}


/**
 * Get currently editing user ID (frontend account/edit profile/edit other user).
 *
 * @return int
 */
function iconic_get_edit_user_id() {
    return isset( $_GET['user_id'] ) ? (int) $_GET['user_id'] : get_current_user_id();
}


/**
 * Save registration fields.
 *
 * @param int $customer_id
 */
function iconic_save_account_fields( $customer_id ) {
    $fields         = iconic_get_account_fields();
    $sanitized_data = array();

    foreach ( $fields as $key => $field_args ) {
        if ( ! iconic_is_field_visible( $field_args ) ) {
            continue;
        }

        $sanitize = isset( $field_args['sanitize'] ) ? $field_args['sanitize'] : 'wc_clean';
        $value    = isset( $_POST[ $key ] ) ? call_user_func( $sanitize, $_POST[ $key ] ) : '';

        if ( iconic_is_userdata( $key ) ) {
            $sanitized_data[ $key ] = $value;
            continue;
        }

        update_user_meta( $customer_id, $key, $value );
    }

    if ( ! empty( $sanitized_data ) ) {
        $sanitized_data['ID'] = $customer_id;
        wp_update_user( $sanitized_data );
    }
}


add_action( 'personal_options_update', 'iconic_save_account_fields' ); // edit own account admin
add_action( 'edit_user_profile_update', 'iconic_save_account_fields' ); // edit other account
add_action( 'woocommerce_save_account_details', 'iconic_save_account_fields' ); // edit WC account

/**
 * Is this field core user data.
 *
 * @param $key
 *
 * @return bool
 */
function iconic_is_userdata( $key ) {
    $userdata = array(
        'user_pass',
        'user_login',
        'user_nicename',
        'user_url',
        'user_email',
        'display_name',
        'nickname',
        'first_name',
        'last_name',
        'description',
        'rich_editing',
        'user_registered',
        'role',
        'jabber',
        'aim',
        'yim',
        'show_admin_bar_front',
    );

    return in_array( $key, $userdata );
}

/**
 * Is field visible.
 *
 * @param $field_args
 *
 * @return bool
 */
function iconic_is_field_visible( $field_args ) {
    $visible = true;
    $action  = filter_input( INPUT_POST, 'action' );

    if ( is_admin() && ! empty( $field_args['hide_in_admin'] ) ) {
        $visible = false;
    } elseif ( ( is_account_page() || $action === 'save_account_details' ) && is_user_logged_in() && ! empty( $field_args['hide_in_account'] ) ) {
        $visible = false;
    } 

    return $visible;
}

/**
 * Add fields to admin area.
 */
function iconic_print_user_admin_fields() {
    $fields = iconic_get_account_fields();
    ?>
    <h2><?php _e( 'Additional Information', 'iconic' ); ?></h2>
    <table class="form-table" id="iconic-additional-information">
        <tbody>
        <?php foreach ( $fields as $key => $field_args ) { ?>
            <?php
            if ( ! iconic_is_field_visible( $field_args ) ) {
                continue;
            }

            $user_id = iconic_get_edit_user_id();
            $value   = iconic_get_userdata( $user_id, $key );
            ?>
            <tr>
                <th>
                    <label for="<?php echo $key; ?>"><?php echo $field_args['label']; ?></label>
                </th>
                <td>
                    <?php $field_args['label'] = false; ?>
                    <?php woocommerce_form_field( $key, $field_args, $value ); ?>
                </td>
            </tr>
        <?php } ?>
        </tbody>
    </table>
    <?php
}

add_action( 'show_user_profile', 'iconic_print_user_admin_fields', 30 ); // admin: edit profile
add_action( 'edit_user_profile', 'iconic_print_user_admin_fields', 30 ); // admin: edit other users

/**
 * Validate fields on frontend.
 *
 * @param WP_Error $errors
 *
 * @return WP_Error
 */
function iconic_validate_user_frontend_fields( $errors ) {
    $fields = iconic_get_account_fields();

    foreach ( $fields as $key => $field_args ) {
        if ( empty( $field_args['required'] ) ) {
            continue;
        }

        if ( ! isset( $_POST['register'] ) && ! empty( $field_args['hide_in_account'] ) ) {
            continue;
        }

    
        if ( empty( $_POST[ $key ] ) ) {
            $message = sprintf( __( '%s is a required field.', 'iconic' ), '<strong>' . $field_args['label'] . '</strong>' );
            $errors->add( $key, $message );
        }
    }

    return $errors;
}

add_filter( 'woocommerce_save_account_details_errors', 'iconic_validate_user_frontend_fields', 10 )

Soy un novato en programación (especialmente PHP). He intentado diferentes formas de agregar una declaración if para verificar si puedo hacer una funcionalidad donde antes de mostrar la lista de pedidos en la tabla, verifica si la ciudad seleccionada por los conductores coincide con la ciudad en la dirección del cliente y luego muestra los mismos pedidos que la ciudad en la que reside el conductor; si no, no se debe mostrar ningún pedido.

Pero sigo rompiendo mi sitio, agradecería cualquier ayuda (ya que estoy empezando a pensar que tal vez este no es el archivo para agregar este tipo de función).

  • ¿De qué maneras diferentes has intentado agregar esta lógica? Cualquier información adicional hará que sea más fácil ayudar. Tal como lo veo, parece que ha tenido un buen comienzo: solo necesita obtener la información de la cuenta del conductor (parece que es llamando iconic_get_userdata) y luego dentro del bucle de pedidos no reclamados: foreach ( $unclaimed_orders as $driver_order ) {... verifique si la ciudad de la dirección de envío del pedido coincide (suponiendo que entendí el problema correctamente).

    – rasgó

    17 de noviembre de 2020 a las 6:03

  • Una posible solución podría ser modificar la matriz $args, agregando una cláusula “where” para mostrar solo las órdenes dentro del rango del controlador. La lógica sería como tal: “where order.postcode in $arrayOfPostcodesNearDriver”. $arrayOfPostcodesNearDriver = get_postcode_api($driver_postcode, $allowed_range). Esta solución permite que los conductores trabajen en una o más áreas cercanas, según el límite de alcance que defina. Intentaré codificar algo el fin de semana si tengo la oportunidad.

    – Michael Habib

    17 de noviembre de 2020 a las 7:26


avatar de usuario
Mtxz

Esto es lo que haría:

En el lado de las opciones del sitio (opciones personalizadas o a través de la zona de entrega de woocommerce):

  • El administrador almacena una lista de ciudades, con nombre e identificación
  • Puede hacer una lista de campos de opciones de ACF, donde puede completar un nombre de ciudad y una identificación (o código postal) (para evitar realizar consultas basadas solo en el nombre de las ciudades)
  • Woocommerce también tiene opciones de entrega en las que puede almacenar áreas de envío, por lo que puede almacenar sus ciudades aquí y usarlas. Dependiendo de cómo te hayas integrado con Woocommerce.

Del lado del usuario/conductor:

  • Su campo de ciudad adicional debería permitir al usuario seleccionar varias ciudades de la lista que definió
  • Los datos se almacenarán como user_meta una matriz serializada de ID o código postal de ciudades seleccionadas
  • Entonces, cada conductor tiene un código postal / ID de ciudades almacenados como meta del usuario, que puede editar

En el lado del proceso de pago del pedido:

  • Si el código postal de la dirección de entrega está “bloqueado” en la lista de ciudades disponibles que hiciste: genial
  • Si el código postal es un campo libre, deberá agregar algo para que el pedido se asocie con un código postal/ID de la ciudad disponible que ha definido. Para poder emparejar conductores y órdenes.
  • Dependiendo de su proceso de pago, puede agregar un campo de pedido para que el cliente seleccione una ciudad según su lista de administradores. O haga que el campo postal_code se limite a su lista. Necesita algo para que un pedido pueda coincidir con una de las ciudades de su lista.

En la página de lista de órdenes de conductor:

  • Editará la consulta WP_query que consulta los pedidos, para agregar una meta_query
  • meta_query consultará los pedidos según el código postal/ID de user_meta del controlador de usuario actual
  • Puede foreach en los valores de la matriz meta del usuario y agregar meta_query “O” para cada ID de ciudad de los conductores/código postal a la consulta de pedidos
  • se mostrará el pedido que coincida con uno de los ID/códigos postales de la ciudad del conductor

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad