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”,以便单击按钮触发再次订单功能,并且我添加了第二个等于“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 );
    }
}