I use the official woocommerce booking plugin and I try do get the quantity of all persons that have booked a product.
for a single order that's no problem with:
if ( is_callable( 'WC_booking_Data_Store::get_booking_ids_from_order_id') ) {
$booking_data = new WC_booking_Data_Store();
$booking_ids = $booking_data->get_booking_ids_from_order_id( $order->get_id() );
}
foreach ( $booking_ids as $booking_id ) {
$booking = new WC_booking( $booking_id );
$person_count = array_sum( $booking->get_person_counts() );
$total_person_count .= 'Booking id: ' . $booking_id . ' Person Count: ' . $person_count . ' ';
}
but how can I collect the sum of all bookings? Hope you can help me
To get all "complete" bookings persons count use the following:
// get all bookings Ids with a status "complete"
$bookings_ids = get_posts( array(
'posts_per_page' => -1,
'post_type' => 'wc_booking', // booking post type
'post_status' => 'complete',
'fields' => 'ids',
));
$persons_count = 0; // Initializing
$persons_html = '<table><tr><th>Booking id</th><th>Persons count</th></tr>'; // Initializing
// Loop through booking Ids
foreach ( $bookings_ids as $booking_id ) {
$booking = new WC_Booking( $booking_id ); // Get the WC_Booking instance object
$count = array_sum( $booking->get_person_counts() );
$persons_count += $count;
$persons_html .= '<tr><td>' . $booking_id . '</td><td>' . $count . '</td></tr>';
}
$persons_html .= '<tr><th><strong>Total count</th><td style="color:red">' . $persons_count . '</td></tr>';
// Output
echo $persons_html . '</table>';
Tested and works.
To make it lighter, you could replace:
$booking = new WC_Booking( $booking_id ); // Get the WC_Booking instance object
$count = array_sum( $booking->get_person_counts() );
simply by:
$count = array_sum( get_post_meta($booking_id, '_booking_persons', true) );
following your updated code, please try this
<?php
if ( is_callable( 'WC_booking_Data_Store::get_booking_ids_from_order_id') ) {
$booking_data = new WC_booking_Data_Store();
$booking_ids = $booking_data->get_booking_ids_from_order_id( $order->get_id() );
}
$total_count_data = array();
$total_count_persons = 0;
foreach ( $booking_ids as $booking_id ) {
$booking = new WC_booking( $booking_id );
$person_count = array_sum( $booking->get_person_counts() );
$total_count_persons+= $person_count;
$total_count_data[] = array(
'Booking' => $booking_id,
'Person' => $person_count
);
}
Related
This question already has answers here:
How to query Woocommerce orders on a page
(2 answers)
Closed 1 year ago.
So I have this code that takes woocommerce orders from yesterday and prints information about them in an email for some reason it is only going through my for loop a max of 10 times and i dont quite understand why any guidance would be fantastic.
<?php
define('WP_USE_THEMES', false);
require( dirname( __FILE__ ) . '/wp-load.php' );
// Date
date_default_timezone_set('PST');
$today = date( 'Y-m-d' );
// Args
$args = array(
'date_created' => $today,
);
// Get WC orders
$orders = \wc_get_orders( $args );
// Initialize
$subtotal = 0;
$gratuity = 0;
$taxes = 0;
// NOT empty
if ( ! empty ( $orders ) ) {
foreach ( $orders as $order ) {
echo $order->get_id();
// Get subtotal
$subtotal += $order->get_subtotal();
// Get fees
foreach ( $order->get_fees() as $fee_id => $fee ) {
$gratuity += $fee['line_total'];
}
// Get tax
$taxes += $order->get_total_tax();
}
}
$convenience = $gratuity;
$gratuity -= .04 * $subtotal;
echo 'Date = ' . $today . ' Subtotal = ' . $subtotal . ' Convenience Fee' . $convenience . ' Gratuity = ' . $gratuity . ' Taxes = ' . $taxes . '';
// Send e-mail
$to = 'jesse#munerismedia.com';
$subject = 'Order totals for today';
$body = '<p>Date = ' . $today . '</p><p>Subtotal = ' . $subtotal . '</p><p>Gratuity = ' . $gratuity . '</p><p>Taxes = ' . $taxes . '</p>';
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
wp_mail( $to, $subject, $body, $headers );
?>
From the documentation (emphasis mine):
limit
Accepts an integer: Maximum number of results to retrieve or -1 for unlimited.
Default: Site 'posts_per_page' setting.
So your posts_per_page setting is probably 10. To get them all, you need to add the limit option to your args array:
$args = array(
'limit' => -1,
'date_created' => $today,
);
$orders = wc_get_orders( $args );
Based on Go through certain WooCommerce orders, collect data and then send the results via email anwer code that is supposed to take all the WooComerce orders from yesterday total them and email them to me, but the email prints 0 for all the values.
<?php
define('WP_USE_THEMES', false);
require( dirname( __FILE__ ) . '/wp-load.php' );
// Date
$yesterday = date( 'Y-m-d', strtotime( ' -1 days ' ) );
// Args
$args = array(
'date_created' => $yesterday,
);
// Get WC orders
$orders = Wc()->wc_get_orders( $args );
// Initialize
$subtotal = 0;
$gratuity = 0;
$taxes = 0;
// NOT empty
if ( ! empty ( $orders ) ) {
foreach ( $orders as $order ) {
// DEBUG information, removed if desired
echo '<p>ID = ' . $order->get_id() . '</p>';
// Get subtotal
$subtotal += $order->get_subtotal();
// Get fees
foreach ( $order->get_fees() as $fee_id => $fee ) {
$gratuity += $fee['line_total'];
}
// Get tax
$taxes += $order->get_total_tax();
}
}
// Send e-mail
$to = 'jesse#munerismedia.com';
$subject = 'Order totals for yesterday';
$body = '<p>Subtotal = ' . $subtotal . '</p><p>Gratuity = ' . $gratuity . '</p><p>Taxes = ' . $taxes . '</p>';
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
wp_mail( $to, $subject, $body, $headers );
?>
I think I might be missing a dependency or something. Btw this is a nightly running cron job.
I'm trying to add product category to the email notification. The custom fields (Time and Date) work but the product category is displaying as an "Array".
function render_product_description($item_id, $item, $order){
$_product = $order->get_product_from_item( $item );
echo "<br>" . $_product->post->post_content;
echo "<br>";
echo '<p><strong>Time:</strong><br />';
echo get_post_meta($_product->id, 'time', true) .'</p>';
echo '<p><strong>Category:</strong><br />';
echo wp_get_post_terms($_product->id, 'product_cat', true) .'</p>';
echo '<p><strong>Date:</strong><br />';
echo get_post_meta($_product->id, 'date', true) .'</p>';
}
add_action('woocommerce_order_item_meta_end', 'render_product_description',10,3);
You can use implode() function that join array values in a string.
I also added an extra check for empty values
function render_product_description( $item_id, $item, $order, $plain_text ) {
// Get product id
$product_id = $item->get_product_id();
// Get product
$product = $item->get_product();
// Product content
$product_content = $product->post->post_content;
// NOT empty
if ( ! empty ( $product_content ) ) {
echo '<p>' . $product_content . '</p>';
}
// Get post meta
$time = get_post_meta( $product_id, 'time', true );
// NOT empty
if ( ! empty ( $time ) ) {
echo '<p><strong>Date:</strong><br />' . $time . '</p>';
}
// Get terms
$term_names = wp_get_post_terms( $product_id, 'product_cat', ['fields' => 'names'] );
// NOT empty
if ( ! empty ( $term_names ) ) {
echo '<p><strong>Categories:</strong><br />' . implode( ", ", $term_names ) . '</p>';
}
// Get post meta
$date = get_post_meta( $product_id, 'date', true );
// NOT empty
if ( ! empty ( $date ) ) {
echo '<p><strong>Date:</strong><br />' . $date . '</p>';
}
}
add_action( 'woocommerce_order_item_meta_end', 'render_product_description', 10, 4 );
In WooCommerce I would like to show recently sold products in a 4 column layout. An example of what I'm going for can be found here: www.hem.com at recently purchased.
So the listing should have the
- Product Name
- Product Price
- Product Thumbnail
- Buyer first name
The listing should show sold out products since all the products are one of a kind.
I've looked at multiple plugins, but most operate by showing a popup or straight up faking the recent purchases.
I want to show actual purchases.
Please follow this code:
function shortcode($atts) {
$param = get_option($this->pref);
$quantity = isset( $param['quntity'] ) ? $param['quntity'] : '5';
$notification = isset( $param['content'] ) ? $param['content'] : "{fname} {lname} purchased {product} for {price} {time} ago";
$img = isset( $param['shortcode_img'] ) ? $param['shortcode_img'] : 'none';
$img_size = isset( $param['shortcode_img_size'] ) ? $param['shortcode_img_size'] : '32';
$args = array(
'numberposts' => $quantity,
'post_status' => 'wc-completed',
'post_type' => 'shop_order',
'suppress_filters' => true,
);
$payments = get_posts( $args );
$out = null;
if($payments){
$out .= '<ul class="wow_woo_recent_purchases">';
foreach ( $payments as $payment ) {
setup_postdata($payment);
$order = new WC_Order($payment->ID);
$fname = $order->get_billing_first_name();
$lname = $order->get_billing_last_name();
$date = $order->get_date_completed();
$time = human_time_diff( strtotime($date), current_time('timestamp') );
$user_id = $order->get_user_id();
$products = $order->get_items();
$product_ids = array();
foreach($products as $product){
$product_ids[] = $product['product_id'];
}
$product_ids = array_unique($product_ids);
$item_id = $product_ids[0];
$product = wc_get_product( $item_id );
$price = $product->get_price_html();
$url = get_permalink($item_id);
$download = ''.$product->get_title().'';
$message = $notification;
$message = str_replace( '{fname}', $fname, $message );
$message = str_replace( '{lname}', $lname, $message );
$message = str_replace( '{product}', $download, $message );
$message = str_replace( '{price}', $price, $message );
$message = str_replace( '{time}', $time, $message );
if($img == 'download'){
$image = get_the_post_thumbnail( $item_id, array($img_size,$img_size), array('class' => 'alignleft') );
$image = ''.$image.'';
}
elseif($img == 'avatar'){
$url = get_avatar_url( $user_id, array('size' => $img_size,'default'=>'monsterid',) );
$image = '<img src="'. $url .'" class="alignleft" width="'.$img_size.'">';
}
else {
$image = null;
}
$out .= '<li>'.$image.' '.$message.'</li>';
}
wp_reset_postdata();
$out .= '</ul>';
}
return $out;
}
Ok so here is my problem: I have a custom field attached to each product where there are a number of checkboxes... The customer checks a maximum of 4 boxes. The results are held in metadata under $key 'Selection'.
I can return only the last of these four choices... How do I list all the selections in a table next to the customer name... Please see below.
This is a shortcode that accepts the product ID so it can be shown anywhere!
Much appreciated!
<?php
// Add Shortcode
function pcl_shortcode( $atts ) {
$output = '';
// Attributes
$customer_atts = shortcode_atts( array(
'product' => get_the_id(),
), $atts );
// Code
global $post, $wpdb;
$post_id = $customer_atts['product'];
$pcl_orders = '';
$columns = array();
$customerquery = "SELECT order_id FROM {$wpdb->prefix}woocommerce_order_itemmeta woim
LEFT JOIN {$wpdb->prefix}woocommerce_order_items oi
ON woim.order_item_id = oi.order_item_id
WHERE meta_key = '_product_id' AND meta_value = %d
GROUP BY order_id;";
$order_ids = $wpdb->get_col( $wpdb->prepare( $customerquery, $post_id ) );
$order_status = get_option( 'pcl_order_status_select', array('wc-completed') );
if( $order_ids ) {
$args = array(
'post_type' =>'shop_order',
'post__in' => $order_ids,
'posts_per_page' => 999,
'order' => 'ASC',
'post_status' => $order_status,
);
$pcl_orders = new WP_Query( $args );
}
if($pcl_orders) {
$output .= '<table>';
foreach($pcl_orders->posts as $pcl_order) {
$order = new WC_Order($pcl_order->ID);
$output .= '<tr>';
$output .= '<td>' . $order->billing_first_name . ' ' . $order->billing_last_name . '</td>';
foreach($order->get_items() as $item)
// get an array of multiple values
$output .= '<td>' . $item['Selection'] . '</td>';
$output .= '</tr>';
}
$output .= '</table>';
}
return $output;
}
add_shortcode( 'woo_customer_list', 'pcl_shortcode' );