phpwordpressdatetimewoocommerceorders

WooCommerce: Get date when order was cancelled


I am trying to get the date when an order was marked as Status: "Cancelled".

My current approach involves getting all order notes using wc_get_order_notes().

Any better approach to get this information?

function get_cancellation_date_with_timezone($order_id) {
    $order = wc_get_order($order_id);

    if (!$order) {
        return false; // Order not found
    }

    // Retrieve all order notes
    $notes = wc_get_order_notes(array('order_id' => $order_id));

    foreach ($notes as $note) {
        // Check if the note indicates a status change to 'Cancelled'
        if (strpos($note->content, 'Order status changed from') !== false && strpos($note->content, 'to Cancelled') !== false) {
            // Get the date created and timezone
            $date_created = $note->date_created;
            $timezone = new DateTimeZone($date_created->getTimezone()->getName());

            // Create a DateTime object with timezone
            $date = new DateTime($date_created->date('Y-m-d H:i:s'), $timezone);

            // Format the date with timezone
            return $date;
        }
    }

    return false; // Cancellation note not found
}

$cancellation_date = get_cancellation_date_with_timezone($order_id = 1234);
echo $cancellation_date->format('Y-m-d\TH:i:sP');

Solution

  • You could use woocommerce_order_status_cancelled dedicated hook to add the cancelled date as WC_Order custom metadata, when an order is cancelled, like (compatible with HPOS):

    add_action( 'woocommerce_order_status_cancelled', 'add_order_cancellation_date', 10, 2 );
    function add_order_cancellation_date( $order_id, $order ) {
        $created_date   = $order->get_date_created(); // Get date (WC_DateTime object)
        $date_timezone  = $created_date->getTimezone(); // Get time zone (DateTimeZone Object)
        $date_cancelled = new WC_DateTime(); // Get current date (WC_DateTime object)
        $date_cancelled->setTimezone($date_timezone); // Set time zone
    
        // Add cancelled date as custom metadata and save
        $order->update_meta_data('date_cancelled', $date_cancelled->format( DateTime::ATOM )); 
        $order->save();
    }
    

    Code goes in functions.php file of your child theme (or in a plugin).

    Then you can get the cancelled order date, from the WC_Order object, using:

    $date_cancelled = $order->get_meta('date_cancelled');
    

    Now for previous canceled orders, you could take the order modified date that reflect the order date of the last edit, using get_date_modified() method like:

    $date_cancelled = $order->get_date_modified(); // WC_DateTime object
    

    The you could use add follwowing function that will handle all cases, to get the order cancelled date (return false if the order is not cancelled):

    function wc_get_order_cancelled_date( $order ) {
        if ( ! $order->has_status('cancelled') ) {
            return false;
        }
    
        if ( $date_cancelled = $order->get_meta('date_cancelled') ) {
            return $date_cancelled;
        } else {
            return $order->get_date_modified()->format( DateTime::ATOM );
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin).

    Then you can get the cancelled order date, from the WC_Order object, using:

    $date_cancelled = wc_get_order_cancelled_date( $order ); // Formatted date string or false