WooCommerce: permitir que os usuários editem pedidos de processamento
Publicados: 2018-12-18Como os clientes do WooCommerce podem editar um pedido que acabaram de fazer e pagar? Juro que olhei nos resultados do mecanismo de pesquisa e em outros lugares antes de chegar à conclusão de que precisava codificar isso sozinho.
Por exemplo, um usuário pode querer alterar a data de entrega (se você fornecer isso na página de checkout). Ou talvez eles precisem mudar de tamanho ou decidir sobre um determinado produto no pedido.
De qualquer forma, é chocante para mim que essa funcionalidade não esteja em um plug-in – como de costume, se você estiver interessado em personalizar este snippet/plugin para suas necessidades específicas, sinta-se à vontade para entrar em contato.
Então, vamos ver como é feito!
Snippet (PHP): Permitir que os clientes editem pedidos @ WooCommerce My Account Page
A primeira coisa que precisamos é mostrar o botão “Editar Pedido” apenas para Processar Pedidos . Aqui, estou apenas aproveitando e reutilizando a funcionalidade “Order Again” que o WooCommerce oferece – esse “Order Again” basicamente duplica o pedido fornecido e preenche o carrinho com os mesmos produtos e meta.
Se você me entende, “Editar pedido” é o mesmo que duplicar o pedido que você deseja editar, fazer um novo pedido e excluir o anterior . Pelo menos é assim que eu vejo e fica definitivamente mais fácil dessa maneira.
Para mostrar o botão "Editar pedido" para processar pedidos, precisamos desbloquear o botão "Pedir novamente" (filtro "woocommerce_valid_order_statuses_for_order_again"). Por padrão, isso só é exibido para pedidos concluídos - também precisamos de processamento (parte 1).
Agora posso imprimir o botão “Editar pedido” com o filtro “woocommerce_my_account_my_orders_actions”. Como você pode ver, o “add_query_arg” deve ter “order_again” para que clicar no botão acione uma função de pedido novamente, e também adiciono um segundo “add_query_arg” igual a “edit_order” para que eu saiba que o botão Editar Pedido foi clicado e não a Ordem Novamente. O botão “name” muda para “Edit Order” (parte 2).
Ótimo - agora o botão aparecerá em Minha conta > Pedidos para processar pedidos, e ao clicar isso redirecionará para uma URL do carrinho que conterá um parâmetro (e o carrinho será preenchido com os mesmos produtos, graças ao parâmetro "order_again" ). Agora posso simplesmente “ouvir” isso e ver se o botão foi clicado durante “woocommerce_cart_loaded_from_session”. Eu posso usar “$_GET” para ver se o URL contém parâmetros – e se sim, eu adiciono o ID do pedido editado à sessão do carrinho (parte 3).
Agora passo para as partes 4 e 5: quero mostrar um aviso de carrinho que o carrinho foi preenchido com os mesmos produtos do pedido anterior, e também que um “crédito” foi aplicado ao carrinho atual em forma de desconto (“ add_fee”) – sim, é um desconto igual ao mesmo valor do total do pedido pago anteriormente.
Atualização de janeiro de 2019: observe que add_fee() não funciona bem ao usar valores negativos E você tem impostos ativados. Neste caso, você precisaria encontrar uma alternativa.
E então passamos para a seção final, parte 6: se o cliente fizer o pedido, claramente precisamos cancelar o pedido “editado” e mostrar um aviso na página de administração do pedido de ambos os pedidos, incluindo um link para o pedido relevante ( cancelado ou novo, respectivamente). Para isso, utilizo a função “add_order_note”.
Bem, uma longa explicação, mas espero que isso seja útil
/**
* @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 );
}
}