WooCommerce: разрешить пользователям редактировать заказы на обработку
Опубликовано: 2018-12-18Как клиенты WooCommerce могут редактировать заказ, который они только что разместили и оплатили? Клянусь, я просмотрел результаты поисковой системы и другие места, прежде чем пришел к выводу, что мне нужно написать это самому.
Например, пользователь может захотеть изменить дату доставки (если вы укажете это на странице оформления заказа). Или, может быть, им нужно изменить размер или определиться с данным продуктом в заказе.
В любом случае, меня шокирует эта функциональность не в плагине - как обычно, если вы заинтересованы в настройке этого фрагмента/плагина для ваших конкретных нужд, не стесняйтесь связаться с нами.
Итак, давайте посмотрим, как это делается!

Фрагмент (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 );
}
}