WooCommerce:允許用戶編輯處理訂單
已發表: 2018-12-18WooCommerce 客戶如何編輯他們剛剛下達並支付的訂單? 我發誓在得出我需要自己編寫代碼的結論之前,我查看了搜索引擎結果和其他地方。
例如,用戶可能想要更改交貨日期(如果您在結帳頁面上提供此日期)。 或者他們可能需要改變尺寸,或者對訂單中的給定產品下定決心。
無論哪種方式,這讓我感到震驚,這個功能不在插件中 - 像往常一樣,如果您有興趣根據您的特定需求自定義此代碼段/插件,請隨時與我們聯繫。
那麼,讓我們看看它是如何完成的!
Snippet (PHP):允許客戶在 WooCommerce 我的帳戶頁面上編輯訂單
我們需要的第一件事是僅顯示處理訂單的“編輯訂單”按鈕。 在這裡,我只是利用並重用 WooCommerce 提供的“再次訂購”功能——這種“再次訂購”基本上複製了給定的訂單並用相同的產品和元數據填充購物車。
如果您明白我的意思,“編輯訂單”與復制您要編輯的訂單、下一個新訂單並刪除之前的訂單是一樣的。 至少我是這麼看的,而且這樣肯定更容易。
為了顯示處理訂單的“編輯訂單”按鈕,我們需要解鎖“再次訂購”按鈕(“woocommerce_valid_order_statuses_for_order_again”過濾器)。 默認情況下,這只顯示已完成的訂單——我們也需要處理(第 1 部分)。
現在我可以使用“woocommerce_my_account_my_orders_actions”過濾器打印“編輯訂單”按鈕。 如您所見,“add_query_arg”必須具有“order_again”,以便單擊按鈕觸發再次訂單功能,並且我添加了第二個等於“edit_order”的“add_query_arg”,以便我知道“編輯訂單”按鈕被單擊並不是再次訂購。 “名稱”按鈕更改為“編輯訂單”(第 2 部分)。
太好了——現在按鈕將顯示在我的帳戶 > 訂單下以處理訂單,單擊此按鈕將重定向到包含參數的購物車 URL(由於“order_again”參數,購物車將填充相同的產品)。 我現在可以簡單地“聽”這個並查看在“woocommerce_cart_loaded_from_session”期間是否單擊了該按鈕。 我可以使用“$_GET”來查看 URL 是否包含參數——如果是,我將編輯的訂單 ID 添加到購物車會話(第 3 部分)。
現在我轉到第 4 部分和第 5 部分:我想顯示一個購物車通知,表明購物車已裝滿與先前訂單相同的產品,並且“信用”已以折扣形式應用於當前購物車(“ add_fee”) – 是的,這是一個折扣,等於之前支付的訂單總額的相同價值。
2019 年 1 月更新:請注意 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 );
}
}