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 );
}
}