Skip to main content

[Thủ Thuật WordPress] Cho phép người dùng "Sửa đơn hàng" trong WooCommerce

Ví dụ khi một người dùng có thể muốn thay đổi ngày giao hàng hoặc có thể họ cần thay đổi kích thước, hoặc quyết định về thay đổi một sản phẩm nhất định trong đơn đặt hàng...Trong khi đơn hàng "Đang xử lý".

Làm cách nào để khách hàng của WooCommerce có thể chỉnh sửa đơn hàng mà họ vừa đặt và thanh toán đó? Dưới đây là Snippet dành cho bạn để cho phép khách sửa đơn hàng đó.

Snippet cho phép khách hàng "Sửa đơn hàng" trong WooCommerce

// ----------------
// 1. Kiểm tra và chỉ cho hiển thị khi đang trong tiến trình hoàng thành đơn hàng
  
add_filter( 'woocommerce_valid_order_statuses_for_order_again', 'devwk_order_again_statuses' );
  
function devwk_order_again_statuses( $statuses ) {
    $statuses[] = 'processing';
    return $statuses;
}
  
// ----------------
// 2.Hiến thị button "Sửa đơn hàng"
  
add_filter( 'woocommerce_my_account_my_orders_actions', 'devwk_add_edit_order_my_account_orders_actions', 50, 2 );
  
function devwk_add_edit_order_my_account_orders_actions( $actions, $order ) {
    if ( $order->has_status( 'processing' ) ) {
        $actions['edit-order'] = array(
            'url'  => wp_nonce_url( add_query_arg( array( 'order_again' => $order->get_id(), 'edit_order' => $order->get_id() ) ), 'woocommerce-order_again' ),
            'name' => __( 'Sửa đơn hàng', 'woocommerce' )
        );
    }
    return $actions;
}
  
// ----------------
// 3. Kiểm tra session khi click nút "Sửa đơn hàng"
  
add_action( 'woocommerce_cart_loaded_from_session', 'devwk_detect_edit_order' );
             
function devwk_detect_edit_order( $cart ) {
    if ( isset( $_GET['edit_order'], $_GET['_wpnonce'] ) && is_user_logged_in() && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'woocommerce-order_again' ) ) WC()->session->set( 'edit_order', absint( $_GET['edit_order'] ) );
}
  
// ----------------
// 4. Hiển thị thông báo sửa giỏ hàng 
  
add_action( 'woocommerce_before_cart', 'devwk_show_me_session' );
  
function devwk_show_me_session() {
    if ( ! is_cart() ) return;
    $edited = WC()->session->get('edit_order');
    if ( ! empty( $edited ) ) {
        $order = new WC_Order( $edited );
        $credit = $order->get_total();
        wc_print_notice( 'Một khoản thanh toán ' . wc_price($credit) . ' đã được áp dụng cho đơn hàng này. Vui lòng thay đổi đơn hàng.', 'notice' );
    }
}
  
// ----------------
// 5. Tính lại đơn hàng mới
   
add_action( 'woocommerce_cart_calculate_fees', 'devwk_use_edit_order_total', 20, 1 );
   
function devwk_use_edit_order_total( $cart ) {
    
  if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
     
  $edited = WC()->session->get('edit_order');
  if ( ! empty( $edited ) ) {
      $order = new WC_Order( $edited );
      $credit = -1 * $order->get_total();
      $cart->add_fee( 'Credit', $credit );
  }
    
}
  
// ----------------
// 6. Lưu lại Order mới với note lại Order cũ và cancel order cũ
  
add_action( 'woocommerce_checkout_update_order_meta', 'devwk_save_edit_order' );
   
function devwk_save_edit_order( $order_id ) {
    $edited = WC()->session->get( 'edit_order' );
    if ( ! empty( $edited ) ) {
        // update this new order
        update_post_meta( $order_id, '_edit_order', $edited );
        $neworder = new WC_Order( $order_id );
        $oldorder_edit = get_edit_post_link( $edited );
        $neworder->add_order_note( 'Đơn đặt hàng sau khi chỉnh sửa. Số đơn đặt hàng cũ: <a href="' . $oldorder_edit . '">' . $edited . '</a>' );
        // cancel previous order
        $oldorder = new WC_Order( $edited );
        $neworder_edit = get_edit_post_link( $order_id );
        $oldorder->update_status( 'cancelled', 'Đơn đặt hàng bị hủy sau khi chỉnh sửa. Số đơn đặt hàng mới:<a href="' . $neworder_edit . '">' . $order_id . '</a> -' );
        WC()->session->set( 'edit_order', null );
    }
}

Giải thích

Ở đây, chúng ta chỉ đang tận dụng và sử dụng lại chức năng “Đặt hàng lại” mà WooCommerce cung cấp sẵn - “Order Again”.

Bạn hiểu quy trình ở đây thực chất cũng giống như việc sao chép đơn hàng bạn muốn chỉnh sửa, tạo thành một đơn hàng mới và xóa đơn hàng trước đó.

Bước đầu tiên chúng ta cần là hiển thị nút “Sửa đơn hàng”.

Bước 1:

Trước khi hiển thị nút “Sửa đơn hàng” chúng tôi cần sử dụng filter “woocommerce_valid_order_statuses_for_order_again” để cho button chỉ  được hiển thị cho các đơn đặt hàng đã hoàn thành và đang chờ được xử lý ( Progressing).

Bước 2:

Bây giờ tôi có thể in nút “Sửa đơn hàng” ta dùng filter “woocommerce_my_account_my_orders_actions”.

Như bạn có thể thấy, “add_query_arg” phải có “order_again” để việc nhấp vào nút kích hoạt function đặt hàng lại và chúng ta cũng thêm một “add_query_arg” thứ hai bằng “edit_order” để chúng ta biết rằng nút "Sửa đơn hàng" đã được click hay là yêu cầu đặt hàng lại đơn hàng mới.

Bây giờ "name" thay đổi thành "Sửa đơn hàng".

Bước 3: 

Bây giờ nút sẽ hiển thị trong trang Tài khoản > Đơn hàng, và khi click vào nut "Sửa đơn hàng" sẽ chuyển hướng đến URL Cart có chứa một tham số (và lúc này Giỏ hàng mới sẽ giống với giỏ hàng gốc giống nhau, nhờ tham số “order_again” ).

Bây giờ chúng ta chỉ cần kiểm tra xem liệu nút có được nhấp hay không thông qua  “woocommerce_cart_loaded_from_session”.

Trong code hiện đang sử dụng “$ _GET” để xem URL có chứa tham số hay không - và nếu có, tôi thêm ID đơn hàng đã chỉnh sửa vào cart session.

Bước 4:

Hiển thị thông báo Giỏ hàng mới đã được tạo giống như đơn hàng trước kèm theo cả số tiền đã thanh toán cảu đơn hàng cũ.

Bước 5: 

Tính lại giá cho Đơn hàng mới và thêm fee mà khách đã đưa từ trước.

Nếu đơn hàng của bạn không thanh toán online, bạn có thể bỏ qua phần credit.

Bước 6: 

Nếu khách hàng đặt hàng, chúng ta rõ ràng cần phải hủy đơn hàng cũ “đã chỉnh sửa” và hiển thị thông báo trong trang quản trị đơn hàng của cả hai đơn hàng cũ và mới về sự thay đổi này, bao gồm một liên kết đến đơn hàng có liên quan ( bị hủy hoặc mới, tương ứng).

Đối với điều này, chúng ta sử dụng chức năng “add_order_note”.