Append a measuring unit to the quantity field in WooCommerce email notifications - wordpress

I'd like to append a unit to the quantity field in the order confirmation email, more precisely in the order items table of that email (email-order-details.php)
See screenshot:
I've tried to add this line of PHP
`<?php echo '<p>VE</p>'; ?>`
into the HTML table in the template file, now my code looks like this:
<div style="margin-bottom: 40px;">
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;" border="1">
<thead>
<tr>
<th class="td" scope="col" style="text-align:<?php echo esc_attr( $text_align ); ?>;"><?php esc_html_e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:<?php echo esc_attr( $text_align ); ?>;"><?php esc_html_e( 'Quantity', 'woocommerce' ); ?> <?php echo '<p>VE</p>'; ?></th>
<th class="td" scope="col" style="text-align:<?php echo esc_attr( $text_align ); ?>;"><?php esc_html_e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<?php
echo wc_get_email_order_items( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$order,
array(
'show_sku' => $sent_to_admin,
'show_image' => false,
'image_size' => array( 32, 32 ),
'plain_text' => $plain_text,
'sent_to_admin' => $sent_to_admin,
)
);
?>
</tbody>
But my adjustment is not showing in the correct location. Can anyone help out with this and hint me in the right direction?

No need to edit/overwrite template files as you can just use the woocommerce_email_order_item_quantity filter hook
So you get:
function filter_woocommerce_email_order_item_quantity( $qty_display, $item ) {
$qty_display = $qty_display . ' VE';
return $qty_display;
}
add_filter( 'woocommerce_email_order_item_quantity', 'filter_woocommerce_email_order_item_quantity', 10, 2 );
Optional: if you don't want to apply this to all e-mail notifications but target specific ones, you can use:
// Setting the email_is as a global variable
function action_woocommerce_email_before_order_table( $order, $sent_to_admin, $plain_text, $email ) {
$GLOBALS['email_id_str'] = $email->id;
}
add_action( 'woocommerce_email_before_order_table', 'action_woocommerce_email_before_order_table', 10, 4 );
function filter_woocommerce_email_order_item_quantity( $qty_display, $item ) {
// Getting the email ID global variable
$refNameGlobalsVar = $GLOBALS;
$email_id = isset( $refNameGlobalsVar['email_id_str'] ) ? $refNameGlobalsVar['email_id_str'] : '';
// Targeting specific email. Multiple statuses can be added, separated by a comma
if ( in_array( $email_id, array( 'new_order' ) ) ) {
$qty_display = $qty_display . ' VE';
}
return $qty_display;
}
add_filter( 'woocommerce_email_order_item_quantity', 'filter_woocommerce_email_order_item_quantity', 10, 2 );
Also see: How to target other WooCommerce order emails
Code goes in functions.php file of the active child theme (or active theme).

Related

Add optional additional fee to checkout

i am using this following code to show the option to add an additional fee (product) to the cart on the "cart" page. It is working great but it is now showing on the cart page, but how do i get it to show on the checkout page additionally:
<?php
/* ADD custom theme functions here */
add_filter( 'woocommerce_price_trim_zeros', 'wc_hide_trailing_zeros', 10, 1 );
function wc_hide_trailing_zeros( $trim ) {
return true;
}
add_action('woocommerce_cart_totals_after_shipping', 'wc_shipping_insurance_note_after_cart');
function wc_shipping_insurance_note_after_cart() {
global $woocommerce;
$product_id = 971;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found ):
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td><?php _e( 'Add ($3)' ); ?> </td>
</tr>
<?php else: ?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td>$3</td>
</tr>
<?php endif;
}
I have tried different methods, and it should be pretty basic but i am rusty on my Functions.php skills.
You could try copying the function and giving it a new name. Then change the hook depending on where you want it on the checkout page.
Here is a great visual guide to the hooks on the checkout page: https://www.businessbloomer.com/woocommerce-visual-hook-guide-checkout-page/
Try something like this:
Notice how I changed the hook from woocommerce_cart_totals_after_shipping to woocommerce_before_checkout_form here you can experiment using the hooks on the guide I linked to. I also changed the name of the function from wc_shipping_insurance_note_after_cart to wc_shipping_insurance_note_after_checkout to avoid conflicts.
add_action('woocommerce_before_checkout_form', 'wc_shipping_insurance_note_after_checkout');
function wc_shipping_insurance_note_after_checkout() {
global $woocommerce;
$product_id = 971;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found ):
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td><?php _e( 'Add ($3)' ); ?> </td>
</tr>
<?php else: ?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td>$3</td>
</tr>
<?php endif;
}
Edit per comment. You could try something like this if you only want to add the table row if a product in the cart has a certain category.
You will have to change "example-category" in $categories = array('example-category'); to your category slug.
add_action('woocommerce_before_checkout_form','wc_shipping_insurance_note_after_checkout');
function wc_shipping_insurance_note_after_checkout() {
global $woocommerce;
$categories = array('example-category');
$found = false;
//loop trough cart items
foreach ( WC()->cart->get_cart_contents() as $cart_item_key => $cart_item ) {
$product_id = $cart_item['product_id'];
//Check if product has category
if ( has_term( $categories, 'product_cat', $product_id ) ) {
$found = true;
}
}
// Do this if product has category
if ( $found ) {
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td><?php _e( 'Add ($3)' ); ?> </td>
</tr>
<?php
} else {
//If product does not have category do this instead
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td>$3</td>
</tr>
<?php
}
}

How do I show custom WooCommerce Subscriptions data on the frontend for customers subscription details?

I am using the WooCommerce Subscriptions plugin to manage recurring orders.
But I want my customers to see custom data, that I add to all new subscriptions, on their subscriptions details page.
I add a variable for the customers baby name, which I add as _baby_name in the subscriptions data post_meta data like this:
/**
* Triggered after a new subscription is created.
*
* #since 2.2.22
* #param WC_Subscription $subscription
*/
function action_wcs_create_subscription( $subscription ) {
// Get ID
$subscription_id = $subscription->get_id();
update_post_meta( $subscription_id, '_baby_name', get_current_user_id() );
}
add_action( 'wcs_create_subscription', 'action_wcs_create_subscription', 10, 1 );
For testing purposes, I just set the value to be get_current_user_id().
To present this custom data on the customers frontend, I have tried to modify the subscription-details.php file:
wp-content/plugins/woocommerce-subscriptions/vendor/woocommerce/subscriptions-core/templates/myaccount/subscription-details.php
I added a row in the top of my subscription_details table, above the status row like this:
<tbody>
<tr>
<td><?php esc_html_e( 'Baby Name', 'woocommerce-subscriptions' ); ?></td>
<td><?php echo esc_html( $subscription.'baby_name' ); ?></td>
</tr>
<tr>
<td><?php esc_html_e( 'Status', 'woocommerce-subscriptions' ); ?></td>
<td><?php echo esc_html( wcs_get_subscription_status_name( $subscription->get_status() ) ); ?></td>
</tr>
But in my new row for Baby Name, I just get all data associated with $subscriptions:
What should I use instead of $subscription.'_baby_name' to pull the value of _baby_name, and show it in the table?
Since the data is saved as post meta, you can use $subscription->get_meta( '_baby_name', true );
So you get:
<tbody>
<tr>
<td><?php esc_html_e( 'Baby Name', 'woocommerce-subscriptions' ); ?></td>
<td><?php echo $subscription->get_meta( '_baby_name', true ); ?></td>
</tr>
<tr>
<td><?php esc_html_e( 'Status', 'woocommerce-subscriptions' ); ?></td>
<td><?php echo esc_html( wcs_get_subscription_status_name( $subscription->get_status() ) ); ?></td>
</tr>
OR use get_post_meta( $subscription->get_id(), '_baby_name', true );
<tbody>
<tr>
<td><?php esc_html_e( 'Baby Name', 'woocommerce-subscriptions' ); ?></td>
<td><?php echo get_post_meta( $subscription->get_id(), '_baby_name', true ); ?></td>
</tr>
<tr>
<td><?php esc_html_e( 'Status', 'woocommerce-subscriptions' ); ?></td>
<td><?php echo esc_html( wcs_get_subscription_status_name( $subscription->get_status() ) ); ?></td>
</tr>
However, if you don't want to edit template files, you can use the wcs_subscription_details_table_before_dates action hook:
function action_wcs_subscription_details_table_before_dates( $subscription ) {
echo '<tr><td>';
echo esc_html_e( 'Baby Name', 'woocommerce-subscriptions' );
echo '</td><td>';
echo get_post_meta( $subscription->get_id(), '_baby_name', true );
echo '</td></tr>';
}
add_action( 'wcs_subscription_details_table_before_dates', 'action_wcs_subscription_details_table_before_dates', 10, 1 );
The only downside to this is that the new row will be displayed below the 'status' row, opposite above

WooCommerce add product image in my account order details

i want to add a new column called image to myaccount-> orders -> view order
in the orders details table which displays the product image for the corresponding product item in the table like this
expected result
what i have tried
function display_remove_order_item_button( $item_id, $item, $order ){
// Avoiding displaying buttons on email notification
if( ! ( is_wc_endpoint_url( 'view-order' ) || is_wc_endpoint_url( 'order-received' ) ) )
return;
$order_id = 569;
$order = wc_get_order( $order_id );
$product = apply_filters( 'woocommerce_order_item_product', $order->get_product_from_item( $item ), $item );
echo $product->get_image();
}
add_action( 'woocommerce_order_details_before_order_table', 'nolo_custom_field_display_cust_order_meta', 10, 1 );
but the image appears inside the product column
how can i achive the function in the picture ?
For that you will need to edit following templates:
templates/order/order-details.php & templates/order/order-details-item.php
First copy both templates in your active theme folder and add this lines
<th class="woocommerce-table__product-image product-image"><?php _e( 'Image', 'woocommerce' ); ?></th>
in order-details.php and
<td class="woocommerce-table__product-image product-image"><?php echo $product->get_image('thumbnail'); ?></td>
in order-details-item.php. If you need a reference of function get_image check this : https://docs.woocommerce.com/wc-apidocs/class-WC_Product.html
order-details.php
<thead>
<tr>
<th class="woocommerce-table__product-name product-name"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="woocommerce-table__product-image product-image"><?php _e( 'Image', 'woocommerce' ); ?></th>
<th class="woocommerce-table__product-table product-total"><?php _e( 'Total', 'woocommerce' ); ?></th>
</tr>
</thead>
order-details-item.php
<td class="woocommerce-table__product-name product-name"></td>
<td class="woocommerce-table__product-image product-image"><?php echo $product->get_image('thumbnail'); ?></td>
<td class="woocommerce-table__product-total product-total">
<?php echo $order->get_formatted_line_subtotal($item); ?>
</td>
Currently there is no such a hooks / filters to achieved your modifications as per your images. But it can be possible by overridden woocommerce follows templates -
Override "order-details.php" template by copying it to yourtheme/woocommerce/order/order-details.php to add your "Image" header.
Override "order-details-item.php" template by copying it to yourtheme/woocommerce/order/order-details-item.php to add your "Image" to display.

How to change drop down variable in select check box button in woocommerce?

I want to change drop down variables in a select checkbox button in woo commerce.
On product page I would like to to show check box variables instead of drop down variables:
<table class="variations" cellspacing="0">
<tbody>
<?php foreach ( $attributes as $attribute_name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo esc_attr( sanitize_title( $attribute_name ) ); ?>">
<?php echo wc_attribute_label( $attribute_name ); // WPCS: XSS ok. ?></label></td>
<td class="value">
<?php
wc_dropdown_variation_attribute_options( array(
'options' => $options,
'attribute' => $attribute_name,
'product' => $product,
) );
echo end( $attribute_keys ) === $attribute_name ? wp_kses_post( apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . esc_html__( 'Clear', 'woocommerce' ) . '</a>' ) ) : '';
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>

get_post_meta in woocommerce email notifications

I'm trying to get some data from an order in a woocommerce email template, but get_post_meta just returns false. This code works on the thankyou page. I have spent too much time on this. Any help would be appreciated. Thanks!
global $post;
echo "test!!!<br />";
$x = get_post_meta( $order->id, 'attendee_data', true );
$y = get_post_meta( $order->id, 'attendee_test', true );
echo $order->id . '<br />';
echo $x;
echo $y;
I've attached a picture of the sql as well as an email.
SQL: http://i.stack.imgur.com/zUFBa.png
Email: http://i.stack.imgur.com/Uqtih.png
The whole email template:
<?php do_action('woocommerce_email_header', $email_heading); ?>
<p><?php _e( "Your order has been received and is now being processed. Your order details are shown below for your reference:", 'woocommerce' ); ?></p>
<?php do_action( 'woocommerce_email_before_order_table', $order, $sent_to_admin, $plain_text ); ?>
<h2><?php echo __( 'Order:', 'woocommerce' ) . ' ' . $order->get_order_number(); ?></h2>
<table cellspacing="0" cellpadding="6" style="width: 100%; border: 1px solid #eee;" border="1" bordercolor="#eee">
<thead>
<tr>
<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php _e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<?php echo $order->email_order_items_table( $order->is_download_permitted(), true, ( $order->status=='processing' ) ? true : false ); ?>
</tbody>
<tfoot>
<?php
if ( $totals = $order->get_order_item_totals() ) {
$i = 0;
foreach ( $totals as $total ) {
$i++;
?><tr>
<th scope="row" colspan="2" style="text-align:left; border: 1px solid #eee; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td style="text-align:left; border: 1px solid #eee; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
</tr><?php
}
}
?>
</tfoot>
</table>
<?php
global $post;
echo "test!!!<br />";
$x = get_post_meta( $order->id, 'attendee_data', true );
$y = get_post_meta( $order->id, 'attendee_test', true );
echo $order->id . '<br />';
echo $x;
echo $y;
foreach ( $x as $k => $p ) {
echo $k ." ... ". $p;
} ?>
<?php // attendee_order_details($order->get_order_number()) ?>
<?php do_action( 'woocommerce_email_after_order_table', $order, $sent_to_admin, $plain_text ); ?>
<?php do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text ); ?>
<h2><?php _e( 'Customer details', 'woocommerce' ); ?></h2>
<?php if ($order->billing_email) : ?>
<p><strong><?php _e( 'Email:', 'woocommerce' ); ?></strong> <?php echo $order->billing_email; ?></p>
<?php endif; ?>
<?php if ($order->billing_phone) : ?>
<p><strong><?php _e( 'Tel:', 'woocommerce' ); ?></strong> <?php echo $order->billing_phone; ?></p>
<?php endif; ?>
<?php wc_get_template( 'emails/email-addresses.php', array( 'order' => $order ) ); ?>
<?php do_action( 'woocommerce_email_footer' ); ?>
I did some testing based on your info and tried to reproduce your problems.
First I created a function which inserts the post meta (attendee_test and attendee_data) when placing an order (using the woocommerce_checkout_update_order_meta hook like you do).
I added this in my themes functions.php (Note that the values are based on your input (image from db) and are not dynamic, just for testing):
add_action('woocommerce_checkout_update_order_meta', 'add_meta_values', 2);
function add_meta_values($order_id){
// array with attendee data
$attendee_data = array(
array(
'edit' => 'false',
'company' => 'get',
)
);
add_post_meta( $order_id, 'attendee_data', $attendee_data );
add_post_meta( $order_id, 'attendee_test', 'test' );
}
Then I added the following code to the template customer-processing-order.php:
<?php
$attendee_data = get_post_meta( $order->id, 'attendee_data', true );
$attendee_test = get_post_meta( $order->id, 'attendee_test', true );
echo 'Order ID: ' . $order->id . '<br />';
echo 'Attendee Test: ' . $attendee_test . '<br />';
echo 'Attendee Data:<br />';
foreach ( $attendee_data as $k => $data ) {
foreach ($data as $key => $value){
echo $key . ' .. ' . $value . '<br />';
}
} ?>
As you can see I modified it a bit to make it more clear. Also changed the $attendee_data loop because I think that wasn't completely right (needed an extra foreach). Of course this isn't related to the real problem.
Making a testorder will show the following data in the email:
This result demonstrate that get_post_meta is working in the email template based on the code above. (I used Wordpress 4.0.1 and WooCommerce 2.2.10).
If the test above is working fine also in your case then I think that the values are inserted in your database after the email is sent (they are inserted right, but to late).
Another thing you might want to check is resending the confirmation email. You can do this from the Wordpress admin. When you edit an order you have a dropdown 'Actions' on the right side. You can select 'Processing order' under 'Resend order emails'. Then click the refresh icon next to the dropdown and you will receive the order confirmation email again. See screenshot below:
This time you know for sure the values are already in the database before you're sending the email.
Hope this information is helping you to solve the problem.
Well, 'attendee_data' is a serialized object so the third argument passed on the function get_post_meta must be set to false (or omitted).
$x = get_post_meta( $order->id, 'attendee_data', false );

Resources