Save custom values from Woocommerce checkout as custom order meta data - php

In Woocommerce, I have a checkout page (review order) with custom data.
I need to find a hook to register some custom data ($totaleiva_1 and $totalefinitocarrello) in the order and then I have to send them in email new order.
I'm not able to make it for instance. Any advice or help please?
Edit - That is my code:
$totaleiva_1 = 0;
$items = $woocommerce->cart->get_cart();
foreach($items as $item ) {
$totaleiva_1 += $totalForSebeneArray[$item ['data']->get_id()];
}
$totaleiva_1 = number_format($totaleiva_1, 2, '.', '');
$totalefinitocarrello = $totaleiva_1 + $total; echo "€";
echo $totalefinitocarrello;

You will need to add and display 2 hidden fields with the 2 desired values (to be able to get and save them as custom order meta data on submission).
Also your code is a bit outdated and can be simplified.
Here is your revisited code:
$totaleiva_1 = 0;
// Loop through cart items
foreach (WC()->cart->get_cart() as $cart_item ) {
$totale_iva_1 += $totalForSebeneArray[$cart_item['data']->get_id()];
}
$totale_finito_carrello = wc_price( $totale_iva_1 + $total );
echo $totale_finito_carrello;
// Display 2 hidden input fields
echo '<input type="hidden" id="totaleiva1" name="totaleiva1" value="'.$totale_iva_1.'">
<input type="hidden" id="tfcarrello" name="tfcarrello" value="'.$totale_finito_carrello.'">';
Then you will save that data as custom order meta data using:
add_action('woocommerce_checkout_create_order', 'save_order_custom_meta_data', 10, 2 );
function save_order_custom_meta_data( $order, $data ) {
if( isset($_POST['totaleiva1']) && ! empty($_POST['totaleiva1']) ) {
$order->update_meta_data( '_totale_iva_1', esc_attr( $_POST['totaleiva1'] ) );
}
if( isset($_POST['tfcarrello']) && ! empty($_POST['tfcarrello']) ) {
$order->update_meta_data( '_totale_fin_carrello', esc_attr( $_POST['tfcarrello'] ) );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Now to get that data and use it anywhere:
1) from the order ID variable, use:
$totaleiva_1 = get_post_meta( $order_id, '_totale_iva_1', true );
$totalefinitocarrello = get_post_meta( $order_id, '_totale_fin_carrello', true );
2 from the WC_Order Object:
$totaleiva_1 = $order->get_meta('_totale_iva_1');
$totalefinitocarrello = $order->get_meta('_totale_fin_carrello');
To display those in Woocommerce new order notification, ou will use:
add_action( 'woocommerce_email_order_details', 'email_order_details_action_callback', 5, 4 );
function email_order_details_action_callback( $order, $sent_to_admin, $plain_text, $email ){
if( $email->id === 'new_order' ) {
if ( $tiva1 = $order->get_meta('_totale_iva_1') ) {
echo '<p>'. __("Totale IVA") . ': ' . $tiva1 . '</p>';
}
if ( $tfcarr = $order->get_meta('_totale_fin_carrello') ) {
echo '<p>'. __("Totale finito carrello") . ': ' . $tfcarr . '</p>';
}
}
}
Display the fields in Admin order pages:
add_action( 'woocommerce_admin_order_data_after_billing_address', 'admin_order_after_billing_address_callback', 10, 1 );
function admin_order_after_billing_address_callback( $order ){
if ( $tiva1 = $order->get_meta('_totale_iva_1') ) {
echo '<p>'. __("Totale IVA") . ': ' . $tiva1 . '</p>';
}
if ( $tfcarr = $order->get_meta('_totale_fin_carrello') ) {
echo '<p>'. __("Totale finito carrello") . ': ' . $tfcarr . '</p>';
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Now I think that all your IVA custom calculations can be handled by Woocommerce using available settings possibilities, as you are making things Much more complicated everywhere.

Related

Display product custom fields on WooCommerce Admin Order Items also for variable products

Based on Show custom fields on the order editing page in WooCommerce answer code where I did some slight changes:
add_action( 'woocommerce_before_order_itemmeta', 'add_admin_order_item_custom_fields', 10, 2 );
function add_admin_order_item_custom_fields( $item_id, $item ) {
// Targeting line items type only
if( $item->get_type() !== 'line_item' ) return;
$product = $item-> get_product();
$value1 = $product->get_meta('model_number');
if ( ! empty($value1) ) {
echo '<table cellspacing="0" class="display_meta">';
if ( ! empty($value1) ) {
echo '<tr><th>' . __("Modelnummer", "woocommerce") . ':</th><td>' . $value1 . '</td></tr>';
}
echo '</table>';
}
}
I would like to make that code works for variable products custom fields too.
What do I need to change to make it work for variable products?
The following will get the parent variable product custom field if it is a product variation with no custom field set for it:
add_action( 'woocommerce_before_order_itemmeta', 'add_admin_order_item_custom_fields', 10, 2 );
function add_admin_order_item_custom_fields( $item_id, $item ) {
// Targeting line items type only
if( $item->get_type() !== 'line_item' ) return;
$product = $item->get_product();
$model_number = $product->get_meta('model_number');
// Get the parent variable product custom field if empty value
if( $item->get_variation_id() > 0 && empty($model_number) ) {
$parent_product = wc_get_product( $item->get_product_id() );
$model_number = $parent_product->get_meta('model_number');
}
if ( ! empty($model_number) ) {
echo '<table cellspacing="0" class="display_meta"><tr>
<th>' . __("Model number", "woocommerce") . ': </th>
<td>' . $model_number . '</td>
</tr></table>';
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Add a delivery time based on custom fields calculations for WooCommerce Flat rate Shipping method

I use code that displays a custom field on the product edit page. This text box shows the cooking time on the single product page.
Here is the code:
// Backend: Display additional product fields
add_action( 'woocommerce_product_options_general_product_data', 'add_time_field_general_product_data' );
function add_time_field_general_product_data() {
// Custom Time Field
woocommerce_wp_text_input( array(
'id' => '_custom_time',
'label' => __( 'Time for cooking', 'woocommerce' ),
));
}
// Backend: Save the data value from the custom fields
add_action( 'woocommerce_admin_process_product_object', 'save_time_custom_fields_values' );
function save_time_custom_fields_values( $product ) {
// Save Custom Time Field
if( isset( $_POST['_custom_time'] ) ) {
$product->update_meta_data( '_custom_time', sanitize_text_field( $_POST['_custom_time'] ) );
}
}
// Display custom fields values under item name in checkout
add_filter( 'woocommerce_checkout_cart_item_quantity', 'custom_time_field_checkout_item_name', 10, 3 );
function custom_time_field_checkout_item_name( $item_qty, $cart_item, $cart_item_key ) {
if( $value4 = $cart_item['data']->get_meta('_custom_time') ) {
$item_qty .= '<br /><div class="my-custom-style"><strong>' . __("Time for cooking", "woocommerce") . ':</strong> ' . $value4 . ' min.</div>';
}
return $item_qty;
}
// Display custom fields values on orders and email notifications
add_filter( 'woocommerce_order_item_name', 'custom_time_field_order_item_name', 10, 2 );
function custom_time_field_order_item_name( $item_name, $item ) {
$product = $item->get_product();
if( $value4 = $product->get_meta('_custom_time') ) {
$item_name .= '<br /><span class="my-custom-style"><strong>' . __("Time for cooking", "woocommerce") . ':</strong> ' . $value4 . ' min.</span>';
}
return $item_name;
}
How can get the following functionality based on this code?
For example, a customer adds several dishes to a cart and checkout order. He sees how much time will be cooking this or that dish.
But when the customer chooses the delivery by courier (Flat Rate), in the same block, the delivery time is shown.
Flat Rate = $10
Delivery time = (the longest cooking time is selected from the order) min. + 45 min.
As I understand it, need to get the data of the custom field '_custom_time' when placing the order. Then, somehow need to get the highest value of this field and add 45 minutes.
I ask for your help! I hope that the answer to this question will be useful to many developers.
Try the following codethat will display a delivery time (calculated from the highest item cooking time value + 45 minutes) when a "flat rate" shipping method is selected on checkout page:
add_action( 'woocommerce_after_shipping_rate', 'action_after_shipping_rate_callback', 10, 2 );
function action_after_shipping_rate_callback( $method, $index ) {
$chosen_shipping_id = WC()->session->get( 'chosen_shipping_methods' )[$index];
if( is_checkout() && $method->method_id === 'flat_rate' && $method->id === $chosen_shipping_id ) {
$extra_time = 45; // Additional time to be added
$data_array = []; // Initializing
// Loop through car items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if( $cooking_time = $cart_item['data']->get_meta('_custom_time') ) {
$data_array[] = (int) $cooking_time;
}
}
if ( sizeof($data_array) ) {
$max_time = (int) max($data_array);
$delivery_time = $max_time + $extra_time;
echo '<br><small style="margin-left:2em;border:solid 1px #ccc;padding:2px 5px;"><strong>' . __("Delivery time", "woocommerce") . '</strong>: ' . $delivery_time . ' min.</small>';
}
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
To enable that in cart page too, remove is_checkout() && from the IF statement.

Make variation stock quantity appear on dropdown selection in Woocommerce

Currently this is what it shows in our site with the current code:
The current code shows all the stocks before even clicking on any of the variation/sizes. What our client wants is to only show that specific variation's stock quantity once they are clicked/selected on the drop down.
Does anyone have an idea how to do this?
Current Code:
add_action( 'woocommerce_before_add_to_cart_button', 'display_stock_variations_loop' );
function display_stock_variations_loop(){
global $product;
if ( $product->get_type() == 'variable' ) {
foreach ( $product->get_available_variations() as $key ) {
$attr_string = array();
foreach ( $key['attributes'] as $attr_name => $attr_value ) {
$attr_string[] = $attr_value;
}
if ( $key['max_qty'] > 0 ) {
echo '' . implode( ', ', $attr_string ) . ': ' . $key['max_qty'] . ' in stock<br>';
} else {
echo '' . implode(', ', $attr_string ) . ': out of stock<br>';
}
}
echo '<br>';
}
}
The displayed selected variation stock quantity and status is already managed by woocommerce. You just need to add your "Size" attribute term name value, using the following (without any javascript need):
add_filter( 'woocommerce_get_availability_text', 'filter_variations_availability_text', 10, 2 );
function filter_variations_availability_text( $availability_text, $product ) {
if( $product->get_type() == 'variation' && $product->get_attribute('size') ) {
$availability_text = $product->get_attribute('size') . ': ' . $availability_text;
}
return $availability_text;
}
Code goes in function.php file of your active child theme (active theme). Tested and works.

Add customer email and phone in "Order" column to admin orders list on Woocommerce

I am trying to find a way on how to add the customer phone and email below the name on the WooCommerce order view. See picture for reference where I need to add this information.
Any ideas, tips or pointers on how to make this happen?
The following code will add the billing phone and email under the order number in backend orders list (for Woocommerce 3.3+ only):
add_action( 'manage_shop_order_posts_custom_column' , 'custom_orders_list_column_content', 50, 2 );
function custom_orders_list_column_content( $column, $post_id ) {
if ( $column == 'order_number' )
{
global $the_order;
if( $phone = $the_order->get_billing_phone() ){
$phone_wp_dashicon = '<span class="dashicons dashicons-phone"></span> ';
echo '<br>' . $phone_wp_dashicon . $phone.'</strong>';
}
if( $email = $the_order->get_billing_email() ){
echo '<br><strong>' . $email . '</strong>';
}
}
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
Thank you, worked perfectly.
I had modifed based on my need, adding the code here for others.
add_action( 'manage_shop_order_posts_custom_column' , 'custom_orders_list_column_content', 50, 2 );
function custom_orders_list_column_content( $column, $post_id ) {
if ( $column == 'order_number' )
{
global $the_order;
if( $phone = $the_order->get_billing_phone() ){
$phone_wp_dashicon = '<span class="dashicons dashicons-phone"></span> ';
echo '<br>Mobile: '.'' . $phone.'</strong>';
}
if( $email = $the_order->get_billing_email() ){
echo '<br>Email: '.'' . $email . '';
}
}
}

Passing custom data from cart items to Order meta in Woocommerce 3

I have implemented a custom HTML Form and asking for some data which my customers will pass to place order successfully. Without these details my order has no importance.
For HTML form, I am referencing some custom PHP script which is below and which processes POST data from the Form and creates Cart with these data programmatically. Thanks #LoicTheAztec to help me achieve this.
The script.php file code:
<?php
require_once("../wp-load.php");
$customer_name = $_POST["customer_name"];
$customer_email = $_POST["customer_email"];
$customer_sex = $_POST["customer_sex"];
$customer_age = $_POST["customer_age"];
$product_id = $_POST["product_id"];
$custom_data = array(); // Initializing
if( isset($_POST['customer_name']) && ! empty($_POST['customer_name']) )
$custom_data['custom_data']['name'] = $_POST['customer_name'];
if( isset($_POST['customer_email']) && ! empty($_POST['customer_email']) )
$custom_data['custom_data']['email'] = $_POST['customer_email'];
if( isset($_POST['customer_sex']) && ! empty($_POST['customer_sex']) )
$custom_data['custom_data']['sex'] = $_POST['customer_sex'];
if( isset($_POST['customer_age']) && ! empty($_POST['customer_age']) )
$custom_data['custom_data']['age'] = $_POST['customer_age'];
global $woocommerce;
if (WC()->cart->add_to_cart( $product_id, '1', '0', array(), $custom_data )) {
var_dump($product_id);
} else {
var_dump($customer_name);
}
header("Location: ./checkout");
?>
As you see we have programmatically created a cart item using WC_Cart add_to_cart() method. So, all custom data is being saved to Cart as custom cart item data.
And now, we have also placed a code block into functions.php to print these data on Checkout page.
add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );
function my_custom_checkout_field( $checkout ) {
//var_dump($checkout);
global $woocommerce;
echo '<div id="my_custom_checkout_field"><h2>' . __('Child Info') . '</h2>';
foreach ( $woocommerce->cart->get_cart() as $cart_item ) {
if( isset($cart_item['custom_data']) ) {
$custom_data = $cart_item['custom_data'];
echo("<div>Name: <strong>" . $custom_data['name'] . "</strong></div>");
echo("<div>Email: <strong>" . $custom_data['email'] . "</strong></div>");
echo("<div>Gender: <strong>" . $custom_data['sex'] . "</strong></div>");
echo("<div>Age: <strong>" . $custom_data['age'] . "</strong></div>");
}
}
echo '</div>';
}
Now, I am trying to add these data printed on Checkout page to the Order page as well. As my order can't be completed without these data, user need to fill up these data and when he creates order, these data needs to be passed to the Order Summary page as well. And admin also needs to be able to see these data so he can process the order.
I hope this description clears everything and thanks again #LoicTheAztec to make me able to do this. Thank you very much.
Update 2 - Two steps
1) Saving data:
We will save this custom customer data as "Hidden" order "item" meta data and then as order meta data too as this is related to subscriptions with a unique order item:
// Utility function: array of custom customer key/label pairs
function custom_data_keys_labels(){
return array(
'name' => __('Customer name'), 'email' => __('Customer email'),
'sex' => __('Customer gender'), 'age' => __('Customer age'),
);
}
// Add/save custom field value as custom HIDDEN order item meta data
add_action( 'woocommerce_checkout_create_order_line_item', 'custom_field_update_order_item_meta', 20, 4 );
function custom_field_update_order_item_meta( $item, $cart_item_key, $values, $order ) {
if ( ! isset( $values['custom_data'] ) )
return;
$custom_data = $values['custom_data'];
$meta_data = array();
$labels_keys = custom_data_keys_labels();
foreach( $labels_keys as $key => $label ){
if ( isset( $custom_data[$key] ) )
$meta_data[$key] = $custom_data[$key];
}
if ( sizeof( $meta_data ) > 0 )
$item->update_meta_data( __('_customer_data'), $meta_data );
return $cart_item_data;
}
// Add/save custom fields values as custom order meta data
add_action( 'woocommerce_checkout_create_order', 'my_custom_checkout_field_update_order_meta', 20, 2 );
function my_custom_checkout_field_update_order_meta( $order, $data ) {
$order_items = $order->get_items(); // Order itesm
$item = reset($order_items); // Keep only the first order item
$item_data = $item->get_meta( '_customer_data' ); // Get custom customer data
if( is_array($item_data) && sizeof($item_data) > 0 ){
foreach( $item_data as $key => $value ) {
if ( isset( $item_data[$key] ) )
$order->update_meta_data( '_customer_' . $key, $value );
}
// Mark as data saved
$order->update_meta_data( '_customer_data_set', true );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
2) Displaying saved custom data:
The code below also use our utility function custom_data_keys_labels()…
// Order pages (frontend and admin) display
add_filter( 'woocommerce_order_details_after_order_table' , 'display_admin_order_meta_cutom_data', 20, 1 ); // Front
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_admin_order_meta_cutom_data', 20, 1 ); // Admin
function display_admin_order_meta_cutom_data( $order ){
$labels_keys = custom_data_keys_labels();
if( $order->get_meta( '_customer_data_set' ) ){
if( is_admin() ){ // Admin
echo '<p>';
foreach( $labels_keys as $key => $label ){
if ( $order->get_meta( '_customer_' . $key ) )
echo '<strong>' . $label . ':</strong> ' . $order->get_meta( '_customer_' . $key ) . '<br>';
}
echo '</p>';
}
else { // Front end: order view and Order received (thankyou)
echo '<table class="woocommerce-table"><tbody>';
foreach( $labels_keys as $key => $label ){
if ( $order->get_meta( '_customer_' . $key ) )
echo '<tr><th>' . $label . ':</th><td>' . $order->get_meta( '_customer_' . $key ) . '</td></tr>';
}
echo '</tbody></table>';
}
}
}
// Email notifications display
add_filter( 'woocommerce_email_order_meta_fields' , 'display_email_cutom_data', 20, 3 );
function display_email_cutom_data ( $fields, $sent_to_admin, $order ) {
$labels_keys = custom_data_keys_labels();
if( $order->get_meta( '_customer_data_set' ) ){
foreach( $labels_keys as $key => $label ){
$fields['customer_' . $key] = array(
'label' => $label,
'value' => $order->get_meta( '_customer_' . $key ),
);
}
}
return $fields;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Categories