I'm in the process of developing a system where it's imperative to include an order note explaining the reason for order cancellations on my e-commerce website. I've observed a consistent number of orders being canceled for various reasons, and the absence of detailed notes from some of my team members has hindered our ability to address these issues effectively.
I've implemented a code solution aimed at making it mandatory for users to input order notes that start with 'order got cancelled because.' The intention is to trigger the order status change to "cancelled" only if this specific string is present in the order note. If the required note is not provided, the system should automatically revert the order status back to its previous state.
However, I've encountered an issue where orders are being marked as "cancelled" even when no relevant note has been added. Despite my efforts, this problem persists, and I'm seeking assistance to resolve this issue. Below is the code I've implemented:
add_action('woocommerce_order_status_changed', 'check_order_status_change', 10, 4);
function check_order_status_change($order_id, $from_status, $to_status, $order) {
// Check if the new status is "cancelled"
if ($to_status === 'cancelled') {
// Get all order notes
$order_notes = $order->get_customer_order_notes();
$cancelled_note_exists = false;
// Check if there's an order note starting with "order got cancelled because"
foreach ($order_notes as $note) {
if (strpos($note->content, 'order got cancelled because') === 0) {
$cancelled_note_exists = true;
break;
}
}
// If a cancellation reason note does not exist, revert the order status
if (!$cancelled_note_exists) {
// Get the previous status from post meta
$previous_status = get_post_meta($order_id, '_status_previous', true);
if (!empty($previous_status)) {
// Update the order status
$order->set_status($previous_status);
$order->save();
// Add an admin note indicating the status change
$order->add_order_note(__('Order status reverted to ' . $previous_status . ' because a cancellation reason was not provided.', 'woocommerce'), true);
}
}
}
}
Try the following instead, that will stop updating status to cancel if there is not an order note with a cancellation reason containing the string "order got cancelled because" (it will also display a warning note):
add_action( 'woocommerce_before_order_object_save', 'process_before_order_object_save', 10, 2 );
function process_before_order_object_save( $order, $data_store ) {
global $pagenow;
// Find out if order status change is "cancelled"
if ( is_admin() && $pagenow === 'post.php' && $order->get_status() === 'cancelled' ) {
$string_to_find = "order got cancelled because";
$note_found = false; // Initializing
// Loop through order notes
foreach(wc_get_order_notes(['order_id' => $order->get_id()]) as $order_note ) {
// Check if there is a note that contains "order got cancelled because"
if ( strpos($order_note->content, $string_to_find) !== false ) {
$note_found = true;
break;
}
}
// If no note found stop status change process
if ( ! $note_found ) {
throw new Exception( "You are not allowed to cancel order without adding a note before with a valid cancellation reason." );
wp_die();
}
}
}
Code goes in functions.php file of your child theme (or in a plugin). Tested and works.
You will also need to remove "mark_cancelled" bulk action from admin orders:
add_filter( 'bulk_actions-edit-shop_order', 'remove_mark_cancelled_bulk_action', 100 );
function remove_mark_cancelled_bulk_action( $bulk_actions ) {
foreach ($bulk_actions as $key => $action) {
if ( 'mark_cancelled' === $key ) {
unset($bulk_actions[$key]);
}
}
return $bulk_actions;
}