I've used the below php to add an 'imported' custom order status in woocommerce and it works fine
> **/ function register_imported_order_status() {
> register_post_status( 'wc-imported', array(
> 'label' => 'Imported',
> 'public' => true,
> 'exclude_from_search' => false,
> 'show_in_admin_all_list' => true,
> 'show_in_admin_status_list' => true,
> 'label_count' => _n_noop( 'Imported <span class="count">(%s)</span>', 'Imported <span class="count">(%s)</span>'
> )
> ) ); } add_action( 'init', 'register_imported_order_status' );
>
> // Add to list of WC Order statuses function
> add_imported_to_order_statuses( $order_statuses ) {
>
> $new_order_statuses = array();
>
> // add new order status after processing
> foreach ( $order_statuses as $key => $status ) {
>
> $new_order_statuses[ $key ] = $status;
>
> if ( 'wc-processing' === $key ) {
> $new_order_statuses['wc-imported'] = 'Imported';
> }
> }
>
> return $new_order_statuses; } add_filter( 'wc_order_statuses', 'add_imported_to_order_statuses' );
-
However when I try to bulk update the order status - the custom order status does not appear, how can I add the custom status to the bulk actions in Woocommerce Orders.
Furthermore, i want the imported status to be considered as having payment captured. Right now the system does not report sales $$$s until we change the status to completed - but we want the sales $$ to be available as soon as they checkout. How can I make this status include captured payment?
warm regards
Jacob
I built the solution via this guide
The code I use to bulk-edit the 'imported' status in WooCommerce's Orders page is below
<?php
/*
* Add your custom bulk action in dropdown
* #since 3.5.0
*/
add_filter( 'bulk_actions-edit-shop_order', 'misha_register_bulk_action' ); // edit-shop_order is the screen ID of the orders page
function misha_register_bulk_action( $bulk_actions ) {
$bulk_actions['mark_imported'] = 'Mark Imported'; // <option value="mark_imported">Mark Imported</option>
return $bulk_actions;
}
/*
* Bulk action handler
* Make sure that "action name" in the hook is the same like the option value from the above function
*/
add_action( 'admin_action_mark_imported', 'misha_bulk_process_custom_status' ); // admin_action_{action name}
function misha_bulk_process_custom_status() {
// if an array with order IDs is not presented, exit the function
if( !isset( $_REQUEST['post'] ) && !is_array( $_REQUEST['post'] ) )
return;
foreach( $_REQUEST['post'] as $order_id ) {
$order = new WC_Order( $order_id );
$order_note = 'That\'s what happened by bulk edit:';
$order->update_status( 'imported', $order_note, true ); //
}
//using add_query_arg() is not required, you can build your URL inline
$location = add_query_arg( array(
'post_type' => 'shop_order',
'marked_imported' => 1, // markED_imported=1 is the $_GET variable for notices
'changed' => count( $_REQUEST['post'] ), // number of changed orders
'ids' => join( $_REQUEST['post'], ',' ),
'post_status' => 'all'
), 'edit.php' );
wp_redirect( admin_url( $location ) );
exit;
}
/*
* Notices
*/
add_action('admin_notices', 'misha_custom_order_status_notices');
function misha_custom_order_status_notices() {
global $pagenow, $typenow;
if( $typenow == 'shop_order'
&& $pagenow == 'edit.php'
&& isset( $_REQUEST['marked_imported'] )
&& $_REQUEST['marked_imported'] == 1
&& isset( $_REQUEST['changed'] ) ) {
$message = sprintf( _n( 'Order status changed.', '%s order statuses changed.', $_REQUEST['changed'] ), number_format_i18n( $_REQUEST['changed'] ) );
echo "<div class=\"updated\"><p>{$message}</p></div>";
}
}
Related
I'm trying to make a button that changes my order status, but it can only appear on the view-quote page when the order status is at: ywraq-pending
I'm trying this code, but it shows up in all statuses:
function customer_order_confirm_args( $order_id ) {
return array(
'url' => wp_nonce_url( add_query_arg( 'complete_order', $order_id ) , 'wc_complete_order' ),
'name' => __( 'Aprovar Orçamento', 'woocommerce' )
);
}
// Add a custom action button to processing orders (My account > Orders)
add_filter( 'woocommerce_my_account_my_orders_actions', 'complete_action_button_my_accout_orders', 50, 2 );
function complete_action_button_my_accout_orders( $actions, $order ) {
if ( $order->has_status( 'ywraq-pending' ) ) {
$actions['order_confirmed'] = customer_order_confirm_args( $order->get_id() );
}
return $actions;
}
// Add a custom button to processing orders (My account > View order)
add_action( 'woocommerce_order_details_after_order_table', 'complete_action_button_my_accout_order_view' );
function complete_action_button_my_accout_order_view( $order ){
// Avoiding displaying buttons on email notification
if( is_wc_endpoint_url( 'view-quote' ) ) {
$data = customer_order_confirm_args( $order->get_id() );
echo '<div style="margin:16px 0 24px;">
<a class="button" href="'.$data['url'].'">'.$data['name'].'</a>
</div>';
}
}
// Change order status and display a message
add_action( 'template_redirect', 'action_complete_order_status' );
function action_complete_order_status( $query ) {
if ( ( is_wc_endpoint_url( 'orders' )
|| is_wc_endpoint_url( 'view-quote' ) )
&& isset( $_GET['complete_order'] )
&& $_GET['complete_order'] > 1
&& isset($_GET['_wpnonce'])
&& wp_verify_nonce($_GET['_wpnonce'], 'wc_complete_order') )
{
$order = wc_get_order( absint($_GET['complete_order']) );
if ( is_a($order, 'WC_Order') ) {
// Change order status to "ywraq-accepted"
$order->update_status( 'ywraq-accepted', __('Approvado pelo cliente', 'woocommerce') ) ;
// Add a notice (optional)
wc_add_notice( sprintf( __( 'Pedido #%s foi aprovado', 'woocommerce' ), $order->get_id() ) );
// Remove query args
wp_redirect( esc_url( remove_query_arg( array( 'complete_order', '_wpnonce' ) ) ) );
exit();
}
}
}
Can anybody help me?
If I understood your question clearly, you missed checking order status in the complete_action_button_my_accout_order_view function, so, you can achieve that with this code:
function customer_order_confirm_args( $order_id ) {
return array(
'url' => wp_nonce_url( add_query_arg( 'complete_order', $order_id ) , 'wc_complete_order' ),
'name' => __( 'Aprovar Orçamento', 'woocommerce' )
);
}
// Add a custom action button to processing orders (My account > Orders)
add_filter( 'woocommerce_my_account_my_orders_actions', 'complete_action_button_my_accout_orders', 50, 2 );
function complete_action_button_my_accout_orders( $actions, $order ) {
if ( $order->has_status( 'ywraq-pending' ) ) {
$actions['order_confirmed'] = customer_order_confirm_args( $order->get_id() );
}
return $actions;
}
// Add a custom button to processing orders (My account > View order)
add_action( 'woocommerce_order_details_after_order_table', 'complete_action_button_my_accout_order_view' );
function complete_action_button_my_accout_order_view( $order ){
// Avoiding displaying buttons on email notification && only for orders with ywraq-pending status
if( is_wc_endpoint_url( 'view-quote' )
&& $order->has_status( 'ywraq-pending' ) ) {
$data = customer_order_confirm_args( $order->get_id() );
echo '<div style="margin:16px 0 24px;"><a class="button" href="'.$data['url'].'">'.$data['name'].'</a></div>';
}
}
// Change order status and display a message
add_action( 'template_redirect', 'action_complete_order_status' );
function action_complete_order_status( $query ) {
if ( ( is_wc_endpoint_url( 'orders' )
|| is_wc_endpoint_url( 'view-quote' ) )
&& isset( $_GET['complete_order'] )
&& $_GET['complete_order'] > 1
&& isset($_GET['_wpnonce'])
&& wp_verify_nonce($_GET['_wpnonce'], 'wc_complete_order') )
{
$order = wc_get_order( absint($_GET['complete_order']) );
if ( is_a($order, 'WC_Order') ) {
// Change order status to "ywraq-accepted"
$order->update_status( 'ywraq-accepted', __('Approvado pelo cliente', 'woocommerce') ) ;
// Add a notice (optional)
wc_add_notice( sprintf( __( 'Pedido #%s foi aprovado', 'woocommerce' ), $order->get_id() ) );
// Remove query args
wp_redirect( esc_url( remove_query_arg( array( 'complete_order', '_wpnonce' ) ) ) );
exit();
}
}
}
I have created custom order status "Ready to dispatch" and custom action button as well.
The problem and question is: when I have clicked on the custom action button, order status has changed, but default action button "Complete" disappeared.
How can I make that after click of custom action button, "Complete" action button retain?
Any advice would be appreciated
My current code:
// Register new status
function register_awaiting_shipment_order_status() {
register_post_status( 'wc-ready-to-dispatch', array(
'label' => 'Ready to dispatch',
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop( 'Ready to dispatch (%s)', 'Ready to dispatch (%s)' )
) );
}
add_action( 'init', 'register_awaiting_shipment_order_status' );
// Add your custom order status action button (for orders with "processing" status)
add_filter( 'woocommerce_admin_order_actions', 'add_custom_order_status_actions_button', 100, 2 );
function add_custom_order_status_actions_button( $actions, $order ) {
// Display the button for all orders that have a 'processing' status
if ( $order->has_status( array( 'processing' ) ) ) {
$action_slug = 'ready-to-dispatch';
// Get Order ID (compatibility all WC versions)
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
// Set the action button
$actions['ready-to-dispatch'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=ready-to-dispatch&order_id=' . $order_id ), 'woocommerce-mark-order-status' ),
'name' => __( 'Ready to dispatch', 'woocommerce' ),
'action' => 'ready-to-dispatch', // keep "view" class for a clean button CSS
);
}
return $actions;
}
// Set Here the WooCommerce icon for your action button
add_action( 'admin_head', 'add_custom_order_status_actions_button_css' );
function add_custom_order_status_actions_button_css() {
$action_slug = 'ready-to-dispatch';
echo '<style>.wc-action-button-'.$action_slug.'::after { font-family: woocommerce !important; content: "\f344" !important; }</style>';
}
// Adding custom status 'awaiting-delivery' to order edit pages dropdown
add_filter( 'wc_order_statuses', 'custom_wc_order_statuses' );
function custom_wc_order_statuses( $order_statuses ) {
$new_order_statuses = array();
// add new order status after processing
foreach ( $order_statuses as $key => $status ) {
$new_order_statuses[ $key ] = $status;
if ( 'wc-processing' === $key ) {
$new_order_statuses['wc-ready-to-dispatch'] = 'Ready to dispatch';
}
}
return $new_order_statuses;
}
// Adding custom status 'awaiting-delivery' to admin order list bulk dropdown
add_filter( 'bulk_actions-edit-shop_order', 'custom_dropdown_bulk_actions_shop_order', 1, 1 );
function custom_dropdown_bulk_actions_shop_order( $actions ) {
$actions['mark_ready-to-dispatch'] = __( 'Ready to dispatch', 'woocommerce' );
return $actions;
}
That's because in the woocommerce_admin_order_actions hook an if condition is missing, to display the button if the order contains the status ready-to-dispatch.
I have rewritten your code with this updated code. For example, the init hook has been replaced with woocommerce_register_shop_order_post_statuses to register custom order statuses.
So you get:
/**
* Register order status
*/
function filter_woocommerce_register_shop_order_post_statuses( $order_statuses ) {
// Status must start with "wc-"
$order_statuses['wc-ready-to-dispatch'] = array(
'label' => _x( 'Ready to dispatch', 'Order status', 'woocommerce' ),
'public' => false,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
/* translators: %s: number of orders */
'label_count' => _n_noop( 'Ready to dispatch <span class="count">(%s)</span>', 'Abonnement <span class="count">(%s)</span>', 'woocommerce' ),
);
return $order_statuses;
}
add_filter( 'woocommerce_register_shop_order_post_statuses', 'filter_woocommerce_register_shop_order_post_statuses', 10, 1 );
/**
* Show order status in the dropdown # single order
*/
function filter_wc_order_statuses( $order_statuses ) {
$new_order_statuses = array();
// add new order status after processing
foreach ( $order_statuses as $key => $status ) {
$new_order_statuses[ $key ] = $status;
if ( 'wc-processing' === $key ) {
// Status must start with "wc-"
$new_order_statuses['wc-ready-to-dispatch'] = _x( 'Ready to dispatch', 'Order status', 'woocommerce' );
}
}
return $new_order_statuses;
}
add_filter( 'wc_order_statuses', 'filter_wc_order_statuses', 10, 1 );
/**
* Show order status in the dropdown # bulk actions
*/
function filter_bulk_actions_edit_shop_order( $bulk_actions ) {
// Note: "mark_" must be there instead of "wc"
$bulk_actions['mark_ready-to-dispatch'] = __( 'Ready to dispatch', 'woocommerce' );
return $bulk_actions;
}
add_filter( 'bulk_actions-edit-shop_order', 'filter_bulk_actions_edit_shop_order', 10, 1 );
/**
* Add quick action button # admin orders list
*/
function filter_order_actions( $actions, $order ) {
// Get Order ID (compatibility all WC versions)
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
// Display the button for all orders that have a 'processing' status
if ( $order->has_status( array( 'processing' ) ) ) {
$action_slug = 'ready-to-dispatch';
// Set the action button
$actions['ready-to-dispatch'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=ready-to-dispatch&order_id=' . $order_id ), 'woocommerce-mark-order-status' ),
'name' => __( 'Ready to dispatch', 'woocommerce' ),
'action' => $action_slug, // keep "view" class for a clean button CSS
);
}
// Display the button for all orders that have a 'ready-to-dispatch' status
if ( $order->has_status( array( 'ready-to-dispatch' ) ) ) {
$action_slug = 'complete';
// Set the action button
$actions['complete'] = array(
'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_status&status=completed&order_id=' . $order_id ), 'woocommerce-mark-order-status' ),
'name' => __( 'Complete', 'woocommerce' ),
'action' => $action_slug,
);
}
return $actions;
}
add_filter( 'woocommerce_admin_order_actions', 'filter_order_actions', 10, 2 );
/**
* Add WooCommerce icon for your action button # admin orders list
*/
function action_admin_head() {
$action_slug = 'ready-to-dispatch';
echo '<style>.wc-action-button-' . $action_slug . '::after { content: "\f344" !important; }</style>';
}
add_action( 'admin_head', 'action_admin_head' );
Via the following code I added a custom order status (Abonnement) in WooCommerce
function register_abonnement_order_status() {
register_post_status( 'wc-abonnement', array(
'label' => 'Abonnement',
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop( 'abonnement (%s)', 'abonnement (%s)' )
) );
}
add_action( 'init', 'register_abonnement_order_status' );
// Add to list of WC Order statuses
function add_abonnement_to_order_statuses( $order_statuses ) {
$new_order_statuses = array();
// add new order status after processing
foreach ( $order_statuses as $key => $status ) {
$new_order_statuses[ $key ] = $status;
if ( 'wc-processing' === $key ) {
$new_order_statuses['wc-abonnement'] = 'Abonnement';
}
}
return $new_order_statuses;
}
add_filter( 'wc_order_statuses', 'add_abonnement_to_order_statuses' );
I then used Change WooCommerce order status based on approved status and specific order item answer code to help me further.
I modified that answer to go to the next step:
function action_woocommerce_order_status_changed( $order_id, $old_status, $new_status, $order ) {
// Compare
if( $old_status === 'processing' ) {
// Get items
$items = $order->get_items();
foreach ( $items as $item ) {
// Get products categories
global $post;
$terms = get_the_terms( $post->ID, 'product_cat' );
foreach ($terms as $term) {
$product_cat_id = $term->term_id;
break;
}
$product_cat = $item->get_product_cat();
if ($product_cat == 249 ) {
$order->update_status( 'abonnement' );
break;
}
}
}
}
add_action( 'woocommerce_order_status_changed', 'action_woocommerce_order_status_changed');
But that doesn't seems to work. So i'm not sure what I'm missing?
Explanation via comment tags added in the code
To automatically change the order status after each order, when the order contains items that belong to certain categories, use:
/**
* Change Order Status
*/
function action_woocommerce_thankyou( $order_id ) {
if ( ! $order_id ) return;
// Get order object
$order = wc_get_order( $order_id );
// Specific categories: the term name/term_id/slug. Several could be added, separated by a comma
$categories = array( 'categorie-1', 'categorie-2', 15, 16 );
// Flag
$found = false;
// Loop through order items
foreach ( $order->get_items() as $item ) {
// Product ID
$product_id = $item->get_variation_id() > 0 ? $item->get_variation_id() : $item->get_product_id();
// Has term (product category)
if ( has_term( $categories, 'product_cat', $product_id ) ) {
$found = true;
break;
}
}
// True
if ( $found ) {
// Status without the "wc-" prefix || Some options: pending, processing, on-hold, completed, cancelled, refunded, failed, etc...
$order->update_status( 'abonnement' );
}
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
OR using woocommerce_order_status_changed hook where you can target your orders statuses transition from and to, to change the order status to any other.
function action_woocommerce_order_status_changed( $order_id, $old_status, $new_status, $order ) {
// Compare
if ( $old_status === 'processing' ) {
// Specific categories: the term name/term_id/slug. Several could be added, separated by a comma
$categories = array( 'categorie-1', 'categorie-2', 15, 16 );
// Flag
$found = false;
// Loop through order items
foreach ( $order->get_items() as $item ) {
// Product ID
$product_id = $item->get_variation_id() > 0 ? $item->get_variation_id() : $item->get_product_id();
// Has term (product category)
if ( has_term( $categories, 'product_cat', $product_id ) ) {
$found = true;
break;
}
}
// True
if ( $found ) {
// Status without the "wc-" prefix || Some options: pending, processing, on-hold, completed, cancelled, refunded, failed, etc...
$order->update_status( 'abonnement' );
}
}
}
add_action( 'woocommerce_order_status_changed', 'action_woocommerce_order_status_changed', 10, 4 );
Optional: to register a new order status, you can replace your current code with this updated code
/**
* Register Order Status
*/
function filter_woocommerce_register_shop_order_post_statuses( $order_statuses ) {
// Status must start with "wc-"
$order_statuses['wc-abonnement'] = array(
'label' => _x( 'Abonnement', 'Order status', 'woocommerce' ),
'public' => false,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
/* translators: %s: number of orders */
'label_count' => _n_noop( 'Abonnement <span class="count">(%s)</span>', 'Abonnement <span class="count">(%s)</span>', 'woocommerce' ),
);
return $order_statuses;
}
add_filter( 'woocommerce_register_shop_order_post_statuses', 'filter_woocommerce_register_shop_order_post_statuses', 10, 1 );
/**
* Show Order Status in the Dropdown # Single Order
*/
function filter_wc_order_statuses( $order_statuses ) {
// Status must start with "wc-"
$order_statuses['wc-abonnement'] = _x( 'Abonnement', 'Order status', 'woocommerce' );
return $order_statuses;
}
add_filter( 'wc_order_statuses', 'filter_wc_order_statuses', 10, 1 );
/**
* Show Order Status in the Dropdown # Bulk Actions
*/
function filter_bulk_actions_edit_shop_order( $bulk_actions ) {
// Note: "mark_" must be there instead of "wc"
$bulk_actions['mark_abonnement'] = __( 'Change status to abonnement', 'woocommerce' );
return $bulk_actions;
}
add_filter( 'bulk_actions-edit-shop_order', 'filter_bulk_actions_edit_shop_order', 10, 1 );
Looking to create a custom order process that looks like this:
Customer adds item to cart
During Checkout Process customer uploads design to order
On Checkout payment is verified, but not captured
After design is finalized by the company, they upload the proof for customer review
the customer reviews proof on their dashboard, and clicks a button that processes the order and captures payment
I have figured out everything i need to make this happen except for how to allow the customer to change the status of their order in the dashboard. I do not need them to edit the order, just approve it for payment capture.
I think there should be an easy way to do this with custom PHP code in conjunction with a plugin like Woocommerce Status Control, but I can't seem to find a solution anywhere.
New improved answer: Allow customer to change order status in WooCommerce
You can use the following code that will:
Replace the button text "view" by "approve" on My account > Orders
Display a custom button to approve the order on My account > Order view (single order)
Display a custom success message once customer has approved an order
This will only happen on customer orders with a specific status. So you will have to define:
The order status that require an approval from customer.
The order status that reflect an approved order by the customer (on the 3 functions)
The button text for order approval
The text that will be displayed once customer has approved the order
The code:
// My account > Orders (list): Rename "view" action button text when order needs to be approved
add_filter( 'woocommerce_my_account_my_orders_actions', 'change_my_account_my_orders_view_text_button', 10, 2 );
function change_my_account_my_orders_view_text_button( $actions, $order ) {
$required_order_status = 'processing'; // Order status that requires to be approved
if( $order->has_status($required_order_status) ) {
$actions['view']['name'] = __("Approve", "woocommerce"); // Change button text
}
return $actions;
}
// My account > View Order: Add an approval button on the order
add_action( 'woocommerce_order_details_after_order_table', 'approve_order_button_process' );
function approve_order_button_process( $order ){
// Avoiding displaying buttons on email notification
if( ! ( is_wc_endpoint_url( 'view-order' ) || is_wc_endpoint_url( 'order-received' ) ) ) return;
$approved_button_text = __("Approve this order", "woocommerce");
$required_order_status = 'processing'; // Order status that requires to be approved
$approved_order_status = 'completed'; // Approved order status
// On submit change order status
if( isset($_POST["approve_order"]) && $_POST["approve_order"] == $approved_button_text
&& $order->has_status( $required_order_status ) ) {
$order->update_status( $approved_order_status ); // Change order status
}
// Display a form with a button for order approval
if( $order->has_status($required_order_status) ) {
echo '<form class="cart" method="post" enctype="multipart/form-data" style="margin-top:12px;">
<input type="submit" class="button" name="approve_order" value="Approve this order" />
</form>';
}
}
// My account > View Order: Add a custom notice when order is approved
add_action( 'woocommerce_order_details_before_order_table', 'approved_order_message' );
function approved_order_message( $order ){
// Avoiding displaying buttons on email notification
if( ! ( is_wc_endpoint_url( 'view-order' ) || is_wc_endpoint_url( 'order-received' ) ) ) return;
$approved_order_status = 'completed'; // Approved order status
if( $order->has_status( $approved_order_status ) ) {
wc_print_notice( __("This order is approved", "woocommerce"), 'success' ); // Message
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
On My account > Orders (list):
On My account > Order view (when an order required to be approved):
On My account > Order view (when customer has approved the order):
For order statuses, you can create custom order statuses with code or with plugins.
I know I might be a bit late. But here I am answering this question in case anyone still needs it.
The below code will add a Mark As Completed button in the My Account Order page action list. Please be informed that it checks if the order status is set to Delivered by the admin and then it shows the button to the customers.
I have developed a plugin for this as well and it's available on WordPress repository. You may check it out in case you need it. Order Approval by Customer for WooCommerce.
/*================================
Add Delivered Order Status
==================================*/
add_action( 'init', 'msoa_register_delivered_order_status' );
function msoa_register_delivered_order_status() {
register_post_status( 'wc-delivered', array(
'label' => 'Session Completed',
'public' => true,
'show_in_admin_status_list' => true,
'show_in_admin_all_list' => true,
'exclude_from_search' => false,
'label_count' => _n_noop( 'Delivered <span class="count">(%s)</span>', 'Delivered <span class="count">(%s)</span>' )
) );
}
add_filter( 'wc_order_statuses', 'msoa_add_delivered_status_to_order_statuses' );
function msoa_add_delivered_status_to_order_statuses( $order_statuses ) {
$new_order_statuses = array();
foreach ( $order_statuses as $key => $status ) {
$new_order_statuses[ $key ] = $status;
if ( 'wc-processing' === $key ) {
$new_order_statuses['wc-delivered'] = __( 'Delivered', 'order-approval' );
}
}
return $new_order_statuses;
}
add_filter( 'woocommerce_my_account_my_orders_actions', 'msoa_mark_as_received', 10, 2 );
function msoa_mark_as_received( $actions, $order ) {
$order_id = $order->id;
if ( ! is_object( $order ) ) {
$order_id = absint( $order );
$order = wc_get_order( $order_id );
}
// check if order status delivered and form not submitted
if ( ( $order->has_status( 'delivered' ) ) && ( !isset( $_POST['mark_as_received'] ) ) ) {
$check_received = ( $order->has_status( 'delivered' ) ) ? "true" : "false";
?>
<div class="ms-mark-as-received">
<form method="post">
<input type="hidden" name="mark_as_received" value="<?php echo esc_attr( $check_received ); ?>">
<input type="hidden" name="order_id" value="<?php echo esc_attr($order_id);?>">
<?php wp_nonce_field( 'so_38792085_nonce_action', '_so_38792085_nonce_field' ); ?>
<input class="int-button-small" type="submit" value="<?php echo esc_attr_e( 'Mark as Received', 'order-approval' ); ?>" data-toggle="tooltip" title="<?php echo esc_attr_e( 'Click to mark the order as complete if you have received the product', 'order-approval' ); ?>">
</form>
</div>
<?php
}
/*
//refresh page if form submitted
* fix status not updating
*/
if( isset( $_POST['mark_as_received'] ) ) {
echo "<meta http-equiv='refresh' content='0'>";
}
// not a "mark as received" form submission
if ( ! isset( $_POST['mark_as_received'] ) ){
return $actions;
}
// basic security check
if ( ! isset( $_POST['_so_38792085_nonce_field'] ) || ! wp_verify_nonce( $_POST['_so_38792085_nonce_field'], 'so_38792085_nonce_action' ) ) {
return $actions;
}
// make sure order id is submitted
if ( ! isset( $_POST['order_id'] ) ){
$order_id = intval( $_POST['order_id'] );
$order = wc_get_order( $order_id );
$order->update_status( "completed" );
return $actions;
}
if ( isset( $_POST['mark_as_received'] ) == true ) {
$order_id = intval( $_POST['order_id'] );
$order = wc_get_order( $order_id );
$order->update_status( "completed" );
}
$actions = array(
'pay' => array(
'url' => $order->get_checkout_payment_url(),
'name' => __( 'Pay', 'woocommerce' ),
),
'view' => array(
'url' => $order->get_view_order_url(),
'name' => __( 'View', 'woocommerce' ),
),
'cancel' => array(
'url' => $order->get_cancel_order_url( wc_get_page_permalink( 'myaccount' ) ),
'name' => __( 'Cancel', 'woocommerce' ),
),
);
if ( ! $order->needs_payment() ) {
unset( $actions['pay'] );
}
if ( ! in_array( $order->get_status(), apply_filters( 'woocommerce_valid_order_statuses_for_cancel', array( 'pending', 'failed' ), $order ), true ) ) {
unset( $actions['cancel'] );
}
return $actions;
}
I have a custom order status - In Progress. The code I have for it is below. It works great - but the orders with this custom order status are not being included in the standard Woo Sales Reports or the Woocommerce Status Dashboard Widget.
Could someone please help me out and take a look and see how I can add to this snippet below so that the $ from this custom order status 'In Progress' are reflected in the Woo Sales Report $.
// 1 New order status AFTER woo 2.2 IN PROGRESS
add_action( 'init', 'register_my_new_order_statuses' );
function register_my_new_order_statuses() {
register_post_status( 'wc-in-progress', array(
'label' => _x( 'In Progress', 'Order status', 'woocommerce' ),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop( 'In Progress <span class="count">(%s)</span>', 'In Progress<span class="count">(%s)</span>', 'woocommerce' )
) );
}
add_filter( 'wc_order_statuses', 'my_new_wc_order_statuses' );
// Register in wc_order_statuses.
function my_new_wc_order_statuses( $order_statuses ) {
$order_statuses['wc-in-progress'] = _x( 'In Progress', 'Order status', 'woocommerce' );
return $order_statuses;
}
/*
* 2 CHANGE STATUSES ORDER IN DROPDOWN LIST
* #param array $wc_statuses_arr Array of all order statuses on the website
*/
function change_statuses_order( $wc_statuses_arr ){
$new_statuses_arr = array(
'wc-processing' => $wc_statuses_arr['wc-processing'], // 1
'wc-in-progress' => $wc_statuses_arr['wc-in-progress'], // 2
'wc-completed' => $wc_statuses_arr['wc-completed'], // 3
'wc-cancelled' => $wc_statuses_arr['wc-cancelled'], // 4
'wc-refunded' => $wc_statuses_arr['wc-refunded'], // 5
'wc-failed' => $wc_statuses_arr['wc-failed'], // 6
'wc-pending' => $wc_statuses_arr['wc-pending'], // 7
'wc-on-hold' => $wc_statuses_arr['wc-on-hold'] // 8
);
return $new_statuses_arr;
}
add_filter( 'wc_order_statuses', 'change_statuses_order' );
/** 3 ADD COLOR TO IN PROGRESS BUTTON **/
add_action('admin_head', 'styling_admin_order_list' );
function styling_admin_order_list() {
global $pagenow;
if( $_GET['post_type'] == 'shop_order' && $pagenow == 'edit.php'):
// HERE below set your custom status
$order_status = 'In Progress'; // <==== HERE
?>
<style>
.order-status.status-<?php echo sanitize_title( $order_status ); ?> {
background: #cc0099;
color: #ffffff;
}
</style>
<?php
endif;
}
You can use the following hooked function, that will add your "custom status" to Orders reports:
add_filter( 'woocommerce_reports_order_statuses', 'include_custom_order_status_to_reports', 20, 1 );
function include_custom_order_status_to_reports( $statuses ){
// Adding the custom order status to the 3 default woocommerce order statuses
return array( 'processing', 'in-progress', 'completed', 'on-hold' );
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
There is a generated error in your 3rd function related to $_GET['post_type'] == 'shop_order'… Instead you can chnage it this way:
// 3. ADD COLOR TO IN PROGRESS BUTTON
add_action('admin_head', 'styling_admin_order_list' );
function styling_admin_order_list() {
global $pagenow, $post;
if( $pagenow != 'edit.php') return; // Exit
if( get_post_type($post->ID) != 'shop_order' ) return; // Exit
// HERE below set your custom status
$order_status = 'In Progress'; // <==== HERE
?>
<style>
.order-status.status-<?php echo sanitize_title( $order_status ); ?> {
background: #cc0099;
color: #ffffff;
}
</style>
<?php
}
It will avoid this small error as post_type is not in the URL of order edit pages (I know is my fault as this was the code of one of my answers)…