WooCommerce: อนุญาตให้ผู้ใช้แก้ไขคำสั่งประมวลผล

เผยแพร่แล้ว: 2018-12-18

ลูกค้า WooCommerce จะแก้ไขคำสั่งซื้อที่เพิ่งวางและชำระเงินได้อย่างไร ฉันสาบานว่าฉันดูผลลัพธ์ของเครื่องมือค้นหาและที่อื่นๆ ก่อนที่จะสรุปได้ว่าฉันต้องเขียนโค้ดนี้ด้วยตัวเอง

ตัวอย่างเช่น ผู้ใช้อาจต้องการเปลี่ยนวันที่จัดส่ง (หากคุณระบุไว้ในหน้าชำระเงิน) หรือบางทีพวกเขาอาจต้องเปลี่ยนขนาด หรือตัดสินใจเกี่ยวกับผลิตภัณฑ์ที่กำหนดตามลำดับ

ไม่ว่าจะด้วยวิธีใด ฟังก์ชันนี้ไม่มีอยู่ในปลั๊กอิน ทำให้ฉันตกใจ ตามปกติ หากคุณสนใจที่จะปรับแต่งข้อมูลโค้ด/ปลั๊กอินนี้สำหรับความต้องการเฉพาะของคุณ โปรดติดต่อ

มาดูกันว่าทำอย่างไร!

แสดงปุ่ม "แก้ไขคำสั่งซื้อ" สำหรับการประมวลผลคำสั่งซื้อเท่านั้น – WooCommerce

Snippet (PHP): อนุญาตให้ลูกค้าแก้ไขคำสั่งซื้อ @ WooCommerce หน้าบัญชีของฉัน

สิ่งแรกที่เราต้องการคือ แสดงปุ่ม "แก้ไขคำสั่งซื้อ" สำหรับการประมวลผลคำสั่งซื้อเท่านั้น ที่นี่ ฉันแค่ใช้ประโยชน์จากฟังก์ชัน "สั่งอีกครั้ง" ที่ WooCommerce เสนอ - "สั่งซื้ออีกครั้ง" นี้โดยพื้นฐานแล้วจะทำซ้ำคำสั่งซื้อที่กำหนดและเติมรถเข็นด้วยผลิตภัณฑ์และเมตาเดียวกัน

หากคุณเข้าใจประเด็นของฉันแล้ว “แก้ไขคำสั่งซื้อ” จะเหมือนกับ การทำซ้ำคำสั่งซื้อที่คุณต้องการแก้ไข การวางคำสั่งซื้อใหม่และการลบคำสั่งซื้อก่อนหน้า อย่างน้อยนี่คือวิธีที่ฉันเห็นและวิธีนี้ง่ายขึ้นอย่างแน่นอน

เพื่อแสดงปุ่ม "แก้ไขคำสั่งซื้อ" สำหรับการประมวลผลคำสั่งซื้อ เราจำเป็นต้องปลดล็อกปุ่ม "สั่งซื้ออีกครั้ง" (ตัวกรอง "woocommerce_valid_order_statuses_for_order_again") โดยค่าเริ่มต้น ระบบจะแสดงเฉพาะคำสั่งซื้อที่เสร็จสมบูรณ์เท่านั้น – เราจำเป็นต้องดำเนินการด้วย (ตอนที่ 1)

ตอนนี้ฉันสามารถพิมพ์ปุ่ม "แก้ไขคำสั่งซื้อ" ด้วยตัวกรอง "woocommerce_my_account_my_orders_actions" อย่างที่คุณเห็น "add_query_arg" ต้องมี "order_again" เพื่อที่การคลิกปุ่มจะเรียกฟังก์ชันคำสั่งอีกครั้ง และฉันเพิ่ม "add_query_arg" ตัวที่สองเท่ากับ "edit_order" เพื่อที่ฉันจะได้รู้ว่ามีการคลิกปุ่มแก้ไขคำสั่งซื้อและ ไม่ใช่คำสั่งอีกครั้ง ปุ่ม "ชื่อ" เปลี่ยนเป็น "แก้ไขคำสั่งซื้อ" (ตอนที่ 2)

เยี่ยมมาก – ตอนนี้ปุ่มจะแสดงภายใต้บัญชีของฉัน > คำสั่งซื้อสำหรับการประมวลผลคำสั่งซื้อ และเมื่อคลิก ระบบจะเปลี่ยนเส้นทางไปยัง URL ของรถเข็นซึ่งจะมีพารามิเตอร์ (และรถเข็นจะถูกกรอกด้วยผลิตภัณฑ์เดียวกันด้วยพารามิเตอร์ "order_again" ). ตอนนี้ฉันสามารถ "ฟัง" และดูว่ามีการคลิกปุ่มระหว่าง "woocommerce_cart_loaded_from_session" หรือไม่ ฉันสามารถใช้ “$_GET” เพื่อดูว่า URL มีพารามิเตอร์หรือไม่ และหากใช่ ฉันจะเพิ่มรหัสคำสั่งซื้อที่แก้ไขไปยังเซสชันรถเข็น (ตอนที่ 3)

ตอนนี้ฉันย้ายไปที่ส่วนที่ 4 และ 5: ฉันต้องการแสดงตะกร้าสินค้า แจ้งให้ทราบว่าตะกร้าสินค้านั้นเต็มไปด้วยสินค้าเดียวกันกับการสั่งซื้อครั้งก่อน และยังมีการใช้ "เครดิต" กับตะกร้าสินค้าปัจจุบันในรูปของส่วนลด (" add_fee") – ใช่ เป็นส่วนลดที่เท่ากับมูลค่ารวมของคำสั่งซื้อที่จ่ายไปก่อนหน้านี้

อัปเดตมกราคม 2019: โปรดทราบว่า add_fee() ทำงานได้ไม่ดีเมื่อใช้จำนวนเงินติดลบและคุณได้เปิดใช้งานภาษี ในกรณีนี้ คุณจะต้องหาทางเลือกอื่น

แล้วเราย้ายไปยังส่วนสุดท้าย ส่วนที่ 6: หากลูกค้าทำการสั่งซื้อ เรา จำเป็นต้องยกเลิกคำสั่งซื้อที่ "แก้ไข" อย่างชัดเจน และแสดงการแจ้งเตือนในหน้าผู้ดูแลระบบคำสั่งซื้อของทั้งสองคำสั่งซื้อ รวมถึงลิงก์ไปยังคำสั่งซื้อที่เกี่ยวข้อง ( ยกเลิกหรือใหม่ตามลำดับ) สำหรับสิ่งนี้ ฉันใช้ฟังก์ชัน “add_order_note”

คำอธิบายยาว แต่หวังว่านี่จะเป็นประโยชน์

/**
 * @snippet       Edit Order Functionality @ WooCommerce My Account Page
 * @how-to        Get CustomizeWoo.com FREE
 * @sourcecode    https://businessbloomer.com/?p=91893
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 4.1
 * @donate $9     https://businessbloomer.com/bloomer-armada/
 */
 
// ----------------
// 1. Allow Order Again for Processing Status
 
add_filter( 'woocommerce_valid_order_statuses_for_order_again', 'bbloomer_order_again_statuses' );
 
function bbloomer_order_again_statuses( $statuses ) {
    $statuses[] = 'processing';
    return $statuses;
}
 
// ----------------
// 2. Add Order Actions @ My Account
 
add_filter( 'woocommerce_my_account_my_orders_actions', 'bbloomer_add_edit_order_my_account_orders_actions', 50, 2 );
 
function bbloomer_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' => __( 'Edit Order', 'woocommerce' )
        );
    }
    return $actions;
}
 
// ----------------
// 3. Detect Edit Order Action and Store in Session
 
add_action( 'woocommerce_cart_loaded_from_session', 'bbloomer_detect_edit_order' );
            
function bbloomer_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. Display Cart Notice re: Edited Order
 
add_action( 'woocommerce_before_cart', 'bbloomer_show_me_session' );
 
function bbloomer_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( 'A credit of ' . wc_price($credit) . ' has been applied to this new order. Feel free to add products to it or change other details such as delivery date.', 'notice' );
    }
}
 
// ----------------
// 5. Calculate New Total if Edited Order
  
add_action( 'woocommerce_cart_calculate_fees', 'bbloomer_use_edit_order_total', 20, 1 );
  
function bbloomer_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. Save Order Action if New Order is Placed
 
add_action( 'woocommerce_checkout_update_order_meta', 'bbloomer_save_edit_order' );
  
function bbloomer_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( 'Order placed after editing. Old order number: <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', 'Order cancelled after editing. New order number: <a href="' . $neworder_edit . '">' . $order_id . '</a> -' );
        WC()->session->set( 'edit_order', null );
    }
}