I am using WooCommerce Bookings to sell tickets to my farm/petting zoo. Customers can buy tickets for specific days and times. I check them in through the WooCommerce app by scanning their order and completing the order. I need a way for orders that never showed up and are now past their date to automatically update to completed so they cannot show up and use their ticket on any day.
I found WooCommerce Bookings - Change Order status from "Pending Payment" to "Cancelled" after 24 hours answer code, which is sort of what I am looking for. However I only want orders that are past their date and not yet completed to change from "processing" to "completed"
This is my code attempt:
function update_booking_status_to_completed() {
// Get all bookings
$args = array(
'post_type' => 'wc_booking',
'post_status' => 'any',
'posts_per_page' => -1,
);
$bookings = get_posts( $args );
foreach ( $bookings as $booking_post ) {
$booking = new WC_Booking( $booking_post->ID );
// Get booking start date
$start_date = $booking->get_start_date();
// Check if start date has passed
if ( strtotime( $start_date ) < current_time( 'timestamp' ) ) {
$order = wc_get_order( $booking->get_order_id() );
// Check if order status is processing
if ( $order->get_status() == 'processing' ) {
// Update order status to completed
$order->update_status( 'completed' );
}
}
}
}
This code could work if someone can check it please.
Updated
It should be better to get all processing orders and check for bookings which start dated has passed.
Try the following instead, that should auto complete processing orders with bookings, which start date is passed (using an hourly scheduled task):
// Define a custom schedule time for Cron schedules tasks
add_filter( 'cron_schedules','hourly_cron_schedule' );
function hourly_cron_schedule( $schedules ) {
if ( ! isset( $schedules["hourly"] ) ) {
$schedules["hourly"] = array(
'interval' => HOUR_IN_SECONDS,
'display' => __( 'Hourly' )
);
}
return $schedules;
}
// Define the scheduled task
add_action('init', 'my_custom_schedule_task');
function my_custom_schedule_task() {
// Schedule an action (if it's not already scheduled)
if ( ! wp_next_scheduled( 'scheduled_complete_processing_orders' ) ) {
wp_schedule_event( time(), 'hourly', 'scheduled_complete_processing_orders' );
}
}
// Function to run on the scheduled event
add_action( 'scheduled_complete_processing_orders', 'complete_processing_orders_with_bookings' );
function complete_processing_orders_with_bookings() {
// Get all processing orders
$orders = wc_get_orders( array(
'type' => 'shop_order',
'limit' => -1,
'status' => 'processing',
) );
// Lopp through processing orders
foreach ( $orders as $order ) {
// Get Bookings (IDs) from the order
$booking_ids = WC_Booking_Data_Store::get_booking_ids_from_order_id( $order->get_id() );
// Only orders with bookings
if( $booking_ids ) {
// Loop through bookings within the order
foreach ( $booking_ids as $booking_id ) {
$booking = new WC_Booking( $booking_id ); // Get the WC_Booking object
// If start date has passed
if ( strtotime( $booking->get_start_date() ) < time() ) {
$order->update_status( 'completed' );
}
}
}
}
}
Code goes in functions.php file of your child theme (or in a plugin). It could work.
To make it work for the next day, it's very simple, just replace this code line:
if ( strtotime( $booking->get_start_date() ) < time() ) {
with:
if ( ( strtotime( $booking->get_start_date() ) + DAY_IN_SECONDS ) < time() ) {