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)…
Related
I created 2 new custom stock statuses:
Out of stock (Permanent)
Out of stock (Supplier)
As you can guess, I want them both to be treated as out of stock.
I used some extra code to hide the products with these custom statuses from the front end but I can not hide them from the ajax search (live) and also someone can add the product in cart.
(I use the Flatsome theme and the live search is from there)
Based on: How to add custom stock status to products in WooCommerce 4+
& Hide all products with a specific stock status from WooCommerce catalog, this is my code attempt:
// Add new stock status options
function filter_woocommerce_product_stock_status_options( $status ) {
// Add new statuses
$status['permanent'] = __( 'Out of stock (Permanent)', 'woocommerce' );
$status['supplier'] = __( 'Out of stock (Supplier)', 'woocommerce' );
return $status;
}
add_filter( 'woocommerce_product_stock_status_options', 'filter_woocommerce_product_stock_status_options', 10, 1 );
// Availability text
function filter_woocommerce_get_availability_text( $availability, $product ) {
// Get stock status
switch( $product->get_stock_status() ) {
case 'permanent':
$availability = __( 'Out of stock (Permanent)', 'woocommerce' );
break;
case 'supplier':
$availability = __( 'Out of stock (Supplier)', 'woocommerce' );
break;
}
return $availability;
}
add_filter( 'woocommerce_get_availability_text', 'filter_woocommerce_get_availability_text', 10, 2 );
// Availability CSS class
function filter_woocommerce_get_availability_class( $class, $product ) {
// Get stock status
switch( $product->get_stock_status() ) {
case 'permanent':
$class = 'permanent';
break;
case 'supplier':
$class = 'supplier';
break;
}
return $class;
}
add_filter( 'woocommerce_get_availability_class', 'filter_woocommerce_get_availability_class', 10, 2 );
// Admin stock html
function filter_woocommerce_admin_stock_html( $stock_html, $product ) {
// Simple
if ( $product->is_type( 'simple' ) ) {
// Get stock status
$product_stock_status = $product->get_stock_status();
// Variable
} elseif ( $product->is_type( 'variable' ) ) {
foreach( $product->get_visible_children() as $variation_id ) {
// Get product
$variation = wc_get_product( $variation_id );
// Get stock status
$product_stock_status = $variation->get_stock_status();
}
}
// Stock status
switch( $product_stock_status ) {
case 'permanent':
$stock_html = '<mark class="permanent" style="background:transparent none;color:#33ccff;font-weight:700;line-height:1;">' . __( 'Out of stock (Permanent)', 'woocommerce' ) . '</mark>';
break;
case 'supplier':
$stock_html = '<mark class="supplier" style="background:transparent none;color:#cc33ff;font-weight:700;line-height:1;">' . __( 'Out of stock (Supplier)', 'woocommerce' ) . '</mark>';
break;
}
return $stock_html;
}
add_filter( 'woocommerce_admin_stock_html', 'filter_woocommerce_admin_stock_html', 10, 2 );
//hide specific stock status
add_action( 'woocommerce_product_query_meta_query', 'custom_product_query_meta_query', 1000 );
function custom_product_query_meta_query( $meta_query ) {
if ( ! is_admin() ) {
$meta_query[] = array(
'key' => '_stock_status',
'value' => 'permanent',
'compare' => '!=',
);
}
if ( ! is_admin() ) {
$meta_query[] = array(
'key' => '_stock_status',
'value' => 'supplier',
'compare' => '!=',
);
}
return $meta_query;
}
Any advice on how to handle both custom stock statuses as out of stock?
Since you indicate in your question that your custom stock statuses should contain the same functionality as the current 'outofstock' status, you can instead of rewrite/reuse all existing functionality of the 'outofstock' status for your custom stock statuses, use a workaround.
This will offer a simple solution, since otherwise you would have to overwrite some template files in addition to writing custom code.
The workaround can be applied as follows:
Step 1) add an extra custom field for your custom statuses, we will add this field under the existing stock status field:
// Add custom field
function action_woocommerce_product_options_stock_status() {
// Custom stock status
$options = array(
'empty' => __( 'N/A', 'woocommerce' ),
'permanent' => __( 'Permanent', 'woocommerce' ),
'supplier' => __( 'Supplier', 'woocommerce' ),
);
woocommerce_wp_select(
array(
'id' => '_custom_stock_status',
'wrapper_class' => 'stock_status_field hide_if_variable hide_if_external hide_if_grouped',
'label' => __( 'Custom stock status', 'woocommerce' ),
'options' => $options,
'desc_tip' => true,
'description' => __( 'Your description', 'woocommerce' ),
)
);
}
add_action( 'woocommerce_product_options_stock_status', 'action_woocommerce_product_options_stock_status', 10 );
// Save custom field
function action_woocommerce_admin_process_product_object( $product ) {
// Isset
if ( isset( $_POST['_custom_stock_status'] ) ) {
// Update
$product->update_meta_data( '_custom_stock_status', sanitize_text_field( $_POST['_custom_stock_status'] ) );
}
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );
Result:
Step 2) when the product is 'out of stock', we will check whether a custom stock status has been set. If this is the case, we will visually change the text using the code below, so that the customer can see the new status. In the background/backend, however, the 'out of stock' status is still used and therefore automatically also the existing functionality:
// Availability text
function filter_woocommerce_get_availability_text( $availability, $product ) {
// Only for 'outofstock'
if ( $product->get_stock_status() == 'outofstock' ) {
// Get custom stock status
$custom_stock_status = $product->get_meta( '_custom_stock_status' );
// Compare and apply new text
if ( $custom_stock_status == 'permanent' ) {
$availability = __( 'Out of stock (Permanent)', 'woocommerce' );
} elseif ( $custom_stock_status == 'supplier' ) {
$availability = __( 'Out of stock (Supplier)', 'woocommerce' );
}
}
return $availability;
}
add_filter( 'woocommerce_get_availability_text', 'filter_woocommerce_get_availability_text', 10, 2 );
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' );
How can I go about displaying the product 'tax status' (ie. taxable, delivery only, none) on the product list of the admin page?
I've been trying to display products as 'In Stock/Out of Stock' and 'Taxable/Not Taxable' on the product list so that I can easily determine the status of products and make changes if necessary.
I figured out how to display the Stock Status on the product list, however, when I try the same with the 'tax status', it doesn't work. I got Stock Status to display by adding the following code to functions.php. How can I have the 'Tax Status' display?
add_filter( 'manage_edit-product_columns', 'product_column_arrange' );
function product_column_arrange( $product_columns ) {
return array(
...
'is_in_stock' => 'Stock',
...
);
}
The following will display a custom column for product tax status in admin product list:
add_filter( 'manage_edit-product_columns', 'tax_status_product_column');
function tax_status_product_column($columns){
$new_columns = [];
foreach( $columns as $key => $column ){
$new_columns[$key] = $columns[$key];
if( $key == 'is_in_stock' ) {
$new_columns['tax_status'] = __( 'Tax status','woocommerce');
}
}
return $new_columns;
}
add_action( 'manage_product_posts_custom_column', 'tax_status_product_column_content', 10, 2 );
function tax_status_product_column_content( $column, $post_id ){
if( $column == 'tax_status' ){
global $post, $product;
// Excluding variable and grouped products
if( is_a( $product, 'WC_Product' ) ) {
$args = array(
'taxable' => __( 'Taxable', 'woocommerce' ),
'shipping' => __( 'Shipping only', 'woocommerce' ),
'none' => _x( 'None', 'Tax status', 'woocommerce' ),
);
echo $args[$product->get_tax_status()];
}
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.
Related: Add custom columns to admin products list in WooCommerce 3
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>";
}
}
I just create a custom status 'tree'('waiting in tree' - labeled) for my orders with the help of Custom Order Status for WooCommerce plugin.
When the user successfully completed the payment the status will change from 'pending' to 'tree'.After some process, I will change the status to processing, at the time I need to send the processing mail to the user. How can I do this, I just find the above code to register the email.
function so_27112461_woocommerce_email_actions( $actions ){
$actions[] = 'woocommerce_order_status_tree_to_processing';
return $actions;
}
add_filter( 'woocommerce_email_actions', 'so_27112461_woocommerce_email_actions' );
But How can i trigger the processing mail.
The plugin your are using is kind of outdated (not updated since WooCommerce 3 release).
You don't need any plugin to do what you want, just this few hooked functions below:
// Add custom status to order list
add_action( 'init', 'register_custom_post_status', 10 );
function register_custom_post_status() {
register_post_status( 'wc-tree', array(
'label' => _x( 'Waiting in tree', '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( 'Waiting in tree <span class="count">(%s)</span>', 'Waiting in tree <span class="count">(%s)</span>', 'woocommerce' )
) );
}
// Add custom status to order page drop down
add_filter( 'wc_order_statuses', 'custom_wc_order_statuses' );
function custom_wc_order_statuses( $order_statuses ) {
$order_statuses['wc-tree'] = _x( 'Waiting in tree', 'Order status', 'woocommerce' );
return $order_statuses;
}
// Adding custom status 'tree' to admin order list bulk dropdown
add_filter( 'bulk_actions-edit-shop_order', 'custom_dropdown_bulk_actions_shop_order', 20, 1 );
function custom_dropdown_bulk_actions_shop_order( $actions ) {
$actions['mark_tree'] = __( 'Mark Waiting in tree', 'woocommerce' );
return $actions;
}
// Enable the action
add_filter( 'woocommerce_email_actions', 'filter_woocommerce_email_actions' );
function filter_woocommerce_email_actions( $actions ){
$actions[] = 'woocommerce_order_status_wc-tree';
return $actions;
}
// Send Customer Processing Order email notification when order status get changed from "tree" to "processing"
add_action('woocommerce_order_status_changed', 'custom_status_email_notifications', 20, 4 );
function custom_status_email_notifications( $order_id, $old_status, $new_status, $order ){
if ( $old_status == 'tree' && $new_status == 'processing' ) {
// Get all WC_Email instance objects
$wc_emails = WC()->mailer()->get_emails();
// Sending Customer Processing Order email notification
$wc_emails['WC_Email_Customer_Processing_Order']->trigger( $order_id );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and Works.