简体   繁体   English

如何添加功能,以便 woocommerce 订单对同一城市的司机用户角色可见?

[英]How to add functionality so woocommerce orders are visible to a driver user-role in the same city?

I have a WordPress Woo-commerce store with the Pro version of the delivery drivers for woo-commerce plugin (https://wordpress.org/plugins/delivery-drivers-for-woocommerce/ ).我有一个 WordPress Woo-commerce 商店,其中包含用于 woo-commerce 插件的专业版交付驱动程序 (https://wordpress.org/plugins/delivery-drivers-for-woocommerce/ )。

Everything works fine as any user who is of user role: 'delivery driver' can view and claim all orders that are processed through the website, at the moment using woo-commerce delivery/shipping zones settings I have configured it so only customers who reside in a certain city can place an order and I am only approving delivery drivers in that area.一切都像任何用户角色的用户一样工作正常:“送货司机”可以查看并声明通过网站处理的所有订单,目前使用 woo-commerce 送货/送货区域设置我已经配置它所以只有居住的客户在某个城市可以下订单,我只批准那个地区的送货司机。

But I want to roll this out to other cities, I can add the postcodes so users can order from those postcodes but the problem is with the delivery drivers plugin - drivers will see all orders from all cities in their dashboard.但我想将其推广到其他城市,我可以添加邮政编码,以便用户可以从这些邮政编码订购,但问题在于送货司机插件 - 司机将在他们的仪表板中看到来自所有城市的所有订单。 I only want the drivers to view and claim orders in the city they reside in (the city they have assigned themselves to).我只希望司机在他们居住的城市(他们分配给自己的城市)查看和领取订单。

Here is the code to the functionality that displays all orders placed on the website to user role type 'delivery driver':以下是向用户角色类型“送货司机”显示网站上所有订单的功能代码:

driver-dashboard-shortcode.php驱动程序仪表板简码.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' );

I had thought of a way to implement this functionality - I have created a custom field (just for delivery drivers) in the woocommerce account details section 'my-account/edit-account'.我想到了一种实现此功能的方法 - 我在 woocommerce 帐户详细信息部分“我的帐户/编辑帐户”中创建了一个自定义字段(仅适用于送货司机)。 The field is a dropdown list of cities a delivery driver can assign to himself in his account details.该字段是送货司机可以在其帐户详细信息中分配给自己的城市的下拉列表。

And I want to call a function that checks if the 'town/city' address label matches the selected city in a drivers profile, if it does then the driver can see that order (orders).我想调用一个 function 检查“城镇/城市”地址 label 是否与司机配置文件中选定的城市匹配,如果匹配,则司机可以看到该订单(订单)。 If a driver has not selected a city in that drop-down then he will not see any orders.如果司机没有在该下拉列表中选择城市,那么他将看不到任何订单。

Here is how I have added the drop-down city list:这是我添加下拉城市列表的方式:

  <?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 )

I am a novice to programming (especially PHP) I have tried different ways in adding a if statement to check if I can make functionality where before it displays the list of orders in the table, it checks if the drivers selected city matches the city in the customers address and then displays the same orders as the city the driver resides in, if not no orders should be displayed.我是编程新手(尤其是 PHP)我尝试了不同的方法来添加一个 if 语句来检查我是否可以在它显示表格中的订单列表之前创建功能,它检查司机选择的城市是否与城市相匹配客户地址,然后显示与司机居住城市相同的订单,否则不应显示任何订单。

But I keep breaking my site, any assistance would be appreciated (as im beginning to think maybe this is not the file to add this sort of function).但是我一直在破坏我的网站,我们将不胜感激(因为我开始认为这可能不是添加此类功能的文件)。

Here's what I would do:这是我会做的:

On the site options side (custom, or trough woocommerce delivery zone options):在网站选项方面(自定义,或通过 woocommerce 送货区选项):

  • Admin store a list of cities, with name and ID管理员存储城市列表,包括名称和 ID
  • You could do an ACF option field list, where you can fill a City name, and an ID (or postcode) (to prevent make queries based on cities name only)您可以做一个 ACF 选项字段列表,您可以在其中填写城市名称和 ID(或邮政编码)(以防止仅根据城市名称进行查询)
  • Woocommerce also has delivery options where you can store shipping areas, so you could store your cities here and use them. Woocommerce 也有送货选项,您可以在其中存储送货区域,因此您可以将您的城市存储在这里并使用它们。 Depending on how you integrated with Woocommerce.取决于您如何与 Woocommerce 集成。

On the user/driver side:在用户/驱动程序方面:

  • Your additional city field should let the user be able to select multiple cities from the list you defined您的附加城市字段应该让用户能够从您定义的列表中选择 select 多个城市
  • Data will store as a user_meta a serialized array of IDs or Postcode from selected cities数据将存储为 user_meta 序列化的 ID 数组或来自选定城市的邮政编码
  • So each driver has a postcode/IDs of cities stored as user meta, that he can edits所以每个司机都有一个邮政编码/城市 ID 存储为用户元,他可以编辑

On the order checkout process side:在订单结账流程方面:

  • If the postcode of delivery address is "locked" to the available cities list you made: great如果送货地址的邮政编码“锁定”到您制作的可用城市列表:很好
  • If the postcode is a free field, you'll need to add something so the order is associated with a postcode/ID of the available city you've defined.如果邮政编码是一个自由字段,您需要添加一些内容,以便订单与您定义的可用城市的邮政编码/ID 相关联。 To be able to match drivers and orders.能够匹配司机和订单。
  • Depending on your checkout process, you could add an order field so the customer selects a city based on your admin list.根据您的结帐流程,您可以添加一个订单字段,以便客户根据您的管理员列表选择一个城市。 Or make the postal_code field limited to your list.或者将 postal_code 字段限制在您的列表中。 You need something so an order can be matched to one of the cities from your list.您需要一些东西,以便订单可以与您列表中的城市之一相匹配。

On the driver orders list page:在司机订单列表页面:

  • You'll edit the WP_query querying that query orders, to add a meta_query您将编辑查询该查询订单的 WP_query,以添加 meta_query
  • meta_query will query orders based on the postcode/IDs of user_meta from the current user driver meta_query 将根据当前用户驱动程序中 user_meta 的邮政编码/ID 查询订单
  • You are able to foreach on the user meta array values, and add meta_query "OR" for each drivers cities ID/Postcode to the orders query您可以 foreach 用户元数组值,并将每个司机城市 ID/邮政编码的元查询“OR”添加到订单查询
  • order matching one of the driver's city IDs/postcodes will be displayed将显示与司机的城市 ID/邮政编码之一匹配的订单

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将用户角色作为自定义元数据添加到WooCommerce订单 - Add a user-role as custom meta data to WooCommerce orders 基于用户角色的登录始终重定向到同一页面 - User-role based login always redirect to the same page 将 woocommerce 的自定义用户角色添加到仅编辑订单 - Add custom User role for woocommerce to Only Edit ORDERS Woocommerce通过用户订单总数更改角色 - Woocommerce change role by total of user orders 如何将用户角色列添加到 Woocommcerce 订单表 - How to Add User Role ColunmTo Woocommcerce Orders table 如何通过将 WordPress 中的所有菜单隐藏到自定义用户角色来仅显示 Woocommerce 订单? - How to show just Woocommerce Orders by hiding all menus in WordPress to custom user role? 根据WooCommerce年度订单数更改用户角色 - Change user role based on WooCommerce yearly orders count WooCommerce 自动将特定用户角色的订单设置为“已完成”状态 - WooCommerce auto set orders to “completed” status for a specific user role WooCommerce订单页面添加客户角色自定义列 - WooCommerce orders page add customer role custom column PHP如何根据用户角色启用或禁用插件或插件功能(WooCommerce保证金)? - PHP How to able or disable a plugin or plugin functionality (WooCommerce deposits) based on user role?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM