WooCommerce: Zezwalaj użytkownikom na edycję zamówień przetwarzania
Opublikowany: 2018-12-18Jak klienci WooCommerce mogą edytować zamówienie, które właśnie złożyli i za które zapłacili? Przysięgam, że zanim doszedłem do wniosku, że sam muszę to zakodować, zajrzałem do wyników wyszukiwania i innych miejsc.
Na przykład użytkownik może chcieć zmienić datę dostawy (jeśli podasz to na stronie kasy). A może muszą zmienić rozmiar lub zdecydować się na dany produkt w zamówieniu.
Tak czy inaczej, jest dla mnie szokujące, że ta funkcja nie jest we wtyczce – jak zwykle, jeśli chcesz dostosować ten fragment/wtyczkę do swoich konkretnych potrzeb, skontaktuj się z nami.
Zobaczmy więc, jak to się robi!
Snippet (PHP): Zezwalaj klientom na edycję zamówień @ WooCommerce Strona Moje konto
Pierwszą rzeczą, której potrzebujemy, jest wyświetlenie przycisku „Edytuj zamówienie” tylko dla zamówień przetwarzania . Tutaj po prostu wykorzystuję i ponownie wykorzystuję funkcję „Zamów ponownie”, którą oferuje WooCommerce – to „Zamów ponownie” w zasadzie duplikuje dane zamówienie i wypełnia koszyk tymi samymi produktami i meta.
Jeśli rozumiesz, „Edytuj zamówienie” jest tym samym, co duplikowanie zamówienia, które chcesz edytować, składanie nowego zamówienia i usuwanie poprzedniego . Przynajmniej tak to widzę i w ten sposób jest to zdecydowanie łatwiejsze.
Aby wyświetlić przycisk „Edytuj zamówienie” do przetwarzania zamówień, musimy odblokować przycisk „Zamów ponownie” (filtr „woocommerce_valid_order_statuses_for_order_again”). Domyślnie wyświetla się to tylko dla zrealizowanych zamówień – my też potrzebujemy przetwarzania (część 1).
Teraz mogę wydrukować przycisk „Edytuj zamówienie” z filtrem „woocommerce_my_account_my_orders_actions”. Jak widać, „add_query_arg” musi mieć „order_again”, aby kliknięcie przycisku uruchomiło funkcję ponownego zamówienia, a także dodaję drugi „add_query_arg” równy „edit_order”, abym wiedział, że przycisk Edytuj zamówienie został kliknięty i nie Zakon Znowu. Przycisk „Nazwa” zmienia się na „Edytuj zamówienie” (część 2).
Świetnie – teraz przycisk wyświetli się pod Moje konto > Zamówienia do realizacji zamówień, a po kliknięciu przekieruje do URL koszyka, który będzie zawierał parametr (a koszyk zostanie wypełniony tymi samymi produktami, dzięki parametrowi „zamów_ponownie” ). Teraz mogę po prostu „posłuchać” tego i zobaczyć, czy przycisk został kliknięty podczas „woocommerce_cart_loaded_from_session”. Mogę użyć „$_GET”, aby sprawdzić, czy adres URL zawiera parametry – a jeśli tak, dodaję edytowany identyfikator zamówienia do sesji koszyka (część 3).
Teraz przechodzę do części 4 i 5: Chcę pokazać koszykowi, że koszyk został wypełniony tymi samymi produktami z poprzedniego zamówienia, a także, że do bieżącego koszyka został zastosowany „kredyt” w postaci rabatu („ add_fee”) – tak, jest to rabat równy tej samej wartości zapłaconej wcześniej sumy zamówienia.
Aktualizacja ze stycznia 2019 r.: pamiętaj, że add_fee() nie działa dobrze, gdy używasz ujemnych kwot ORAZ masz włączone podatki. W takim przypadku musisz znaleźć alternatywę.
A następnie przechodzimy do ostatniej sekcji, część 6: jeśli klient złoży zamówienie, musimy wyraźnie anulować „edytowane” zamówienie i wyświetlić informację na stronie administratora obu zamówień, w tym link do odpowiedniego zamówienia ( odpowiednio anulowane lub nowe). W tym celu używam funkcji „add_order_note”.
Cóż, długie wyjaśnienie, ale mam nadzieję, że jest to pomocne
/**
* @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 );
}
}