I have meta data that is stored below the order line items, many times the data is that same. I am trying to save the unique meta values as order meta data, separated by commas and I if possible to add a text "these are your numbers" before this data.
So far I tried the code below but nothing is happening.
add_action( 'woocommerce_update_order', 'add_unique_order_nummers_to_order', 10, 2 );
function add_unique_order_nummers_to_order( $order_id, $order ) {
$allenummers = array();
$items = $order->get_items();
foreach ( $order->get_items() as $item_id => $item ) {
$allenummers[] = $item->get_meta( '_org_ordernummer', true );
}
$ordernummers_array = array_unique($allenummers);
$ordernummers_unique = implode(',', $ordernummers_array);
update_post_meta( $order_id, '_Unieke_nummers', $ordernummers_unique );
}
I hope someone can help.
Update: Use the following simplified code with a different hook, based on your comment, when order status is changed to "we-fact" custom order status:
add_action('woocommerce_order_status_we-fact', 'add_unique_order_nummers_to_order', 20, 2 );
function add_unique_order_nummers_to_order( $order_id, $order ) {
$allenummers = array(); // Initializing
// Loop through order
foreach ( $order->get_items() as $item ) {
$allenummers[] = $item->get_meta( '_org_ordernummer' );
}
if ( ! empty($allenummers) ) {
$order->update_meta_data('_Unieke_nummers', sprintf( __("These are your numbers: %s"), implode(', ', array_unique($allenummers) ) ) );
}
}
Code goes in functions.php file of the active child theme (or active theme). It should works.
Related
I want to add two types of metadata to an order and its order_items when it is created. I tried some things but it is not working.
The first I want to add is $order->get_date_created(); as meta data to the order.
// Add order date as order meta data
add_action( 'woocommerce_checkout_create_order', 'add_order_date_to_order_meta_data', 10, 2 );
function add_order_date_to_order_meta_data( $order, $data ) {
$order_date = $order->get_date_created();
$order->update_meta_data( 'order_created', $order_date );
}
The second is $order->get_id(); that I want to add to both the order itself as to the order_items
// Add order number as order meta data
add_action( 'woocommerce_checkout_create_order', 'add_order_number_to_order_meta_data', 10, 2 );
function add_order_number_to_order_meta_data( $order, $data ) {
$order_id = $order->get_id();
$order->update_meta_data( 'order_number', $order_id );
}
I am blank about about how to add it to the order lines. No clue on how to do that. I found the following but I believe that is adding information before a order is created?
add_action( 'woocommerce_checkout_create_order_line_item', 'add_meta_to_line_item', 20, 4 );
function add_meta_to_line_item( $item, $cart_item_key, $values, $order )
{
$_p = $item->get_product();
$key = $order->get_id();
if ( false !== ( $value = $_p->get_meta( $key, true ) ) )
$item->add_meta_data( $key, true);
}
Then after I created these meta fields, I also want to add them to a column in the order overview on the front-end.
/**
* Adds a new column to the "My Orders" table in the account.
*
* #param string[] $columns the columns in the orders table
* #return string[] updated columns
*/
function metavalue_add_my_account_orders_column( $columns ) {
$new_columns = array();
foreach ( $columns as $key => $name ) {
$new_columns[ $key ] = $name;
// add meta_value after order status column
if ( 'order-status' === $key ) {
$new_columns['order_number'] = __( 'Order Number', 'textdomain' );
$new_columns['order_created'] = __( 'Order Created', 'textdomain' );
}
}
return $new_columns;
}
add_filter( 'woocommerce_my_account_my_orders_columns', 'metavalue_add_my_account_orders_column' );
I hope someone can help me in the right direction.
Updated - There are some mistakes and missing things in your code. Try the following instead:
// Add order number and order date creation as order meta data
add_action( 'woocommerce_checkout_create_order', 'add_some_order_meta_data', 10, 2 );
function add_some_order_meta_data( $order, $data ) {
$order->update_meta_data( '_order_number', $order->get_id() );
$order->update_meta_data( 'order_date', current_time('Y-m-d H:i:s') );
}
// Add order Id as custom order item meta data
add_action( 'woocommerce_checkout_create_order_line_item', 'add_meta_to_line_item', 10, 4 );
function add_meta_to_line_item( $item, $cart_item_key, $values, $order ) {
$item->add_meta_data( '_order_id', $order->get_id() );
}
// Include order number meta data for the method get_order_number()
add_filter( 'woocommerce_order_number', 'wc_set_order_number', 10, 2 );
function wc_set_order_number( $order_id, $order ) {
// Get the order number (custom meta data)
$order_number = $order->get_meta('_order_number');
return $order_number ? $order_number : $order_id;
}
// Add columns to my account orders
add_filter( 'woocommerce_my_account_my_orders_columns', 'add_my_account_orders_columns' );
function add_my_account_orders_columns( $columns ) {
$new_columns = array();
foreach ( $columns as $key => $name ) {
$new_columns[ $key ] = $name;
// add meta_value after order status column
if ( 'order-status' === $key ) {
$new_columns['number'] = __( 'Order Number', 'textdomain' );
$new_columns['date-created'] = __( 'Date Created', 'textdomain' );
}
}
return $new_columns;
}
// Column order number content
add_action( 'woocommerce_my_account_my_orders_column_number', 'my_account_order_number_column_content', 10, 1 );
function my_account_order_number_column_content( $order ) {
echo $order->get_order_number();
}
// Column order date created content
add_action( 'woocommerce_my_account_my_orders_column_date-created', 'my_account_order_date_created_column_content', 10, 1 );
function my_account_order_date_created_column_content( $order ) {
echo $order->get_meta('order_date') ? $order->get_meta('order_date') : $order->get_date_created()->date('Y-m-d H:i:s');
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Notes:
To get the order number, you will use the WC_Order method get_order_number() from order object.
You can change the saved date format as explained in here for WC_Date_time date() method.
For the order Id stored as custom order item meta data the meta key needs to start with an underscore, to make it not visible in customer order and email notifications. So to get it from order items, you will use WC_Data get_meta() method on the WC_Order_Item_Product object $item variable like $item->get_meta( '_order_id') or you can also use the method get_order_id() like $item->get_order_id()…
Related:
Show products name and quantity in a new column on Woocommerce My account Orders
Set an external order ID when creating programmatically a WooCommerce order?
How to get WooCommerce order details
Get Order items and WC_Order_Item_Product in WooCommerce 3
I am trying to get the variation values selected by customer at checkout from an order (by id or otherwise) to map to variables $storage and $tier which are used to build an API url.
I have tried a variety of methods to get the data onto the variables but the API url is failing, which leads me to believe I do not have the indented values on my variables.
My current code is as follows (extract):
add_action( 'woocommerce_order_status_processing', 'my_function' );
function my_function( $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
foreach ( $items as $key => $item ) {
$storage = get_post_meta( $key, 'attribute_addon-storage' );
$tier = get_post_meta( $key, 'attribute_subscription-type' );
Does anyone have any idea how I would grab the values of those two variables, addon-storage and subscription-type?
I can see the values I want to get in my database in the woocommerce_order_itemmeta table.
Can I get the values from there?
Edit:
So as per LoicTheAztec's advice, the right way to get the value of the data I see in the woocommerce_order_itemmeta table as $meta_key is:
add_action( 'woocommerce_order_status_processing', 'my_function', 10, 1 );
function my_function( $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
foreach ( $items as $key => $item ) {
$storage = wc_get_order_item_meta( $key, 'addon-storage', true );
$tier = wc_get_order_item_meta( $key, 'subscription-type', true );
$anyMetaValue = wc_get_order_item_meta( $key, '$meta_key', true );
// Then I can create the variable I need in the the API url with:
$package = "$tier$storage";
Updated: Your are confusing order post meta data and order item meta data, which are very different things and located in different database tables.
Also your code is incomplete and you will not get anything using get_post_meta() with the $key (which is the item ID)...
The get_post_meta( $order_id, 'meta_key', true ) function will look for Order post meta data (not related to order items) and use Order ID as argument.
The wc_get_order_item_meta( $item_id, 'meta_key', true ) function will look for Order item meta data realated and will use the Item ID as argument (the $key in your code)…
So this function should need to be used in the foreach loop, where you get the order items data, instead.
Then 2 ways:
You should check in your database for the last order ID you have (via phpMyAdmin) in wp_postmeta and wp_woocommerce_order_itemmeta tables, to see where is located the data…
Or you can use the following code (just for testing) that will output the order items raw data where your data is located.
This raw data will be output in the shop, archive and product pages, only visible for logged in admins. You will need to define an order ID in it.
Here is this testing function
add_action( 'woocommerce_before_main_content', 'my_testing_order_function' );
function my_testing_order_function() {
// Define an Order ID
$order_id = 724;
// Only for admin user role
if( ! current_user_can('edit_products')) return;
$order = wc_get_order( $order_id ); // The order object
foreach ( $order->get_items() as $item_id => $item ) {
// Order item meta data Raw output
echo "<pre>ORDER ITEM META DATA - (Item_id $item_id):"; print_r($item->get_data()); echo'</pre>';
echo "<pre>ORDER ITEM META META DATA - (Item_id $item_id):"; print_r($item->get_meta_data()); echo'</pre>';
}
}
Now you have everything needed to locate and get the data. The code below should normally work for you, allowing you to get the data from your variations:
add_action( 'woocommerce_order_status_processing', 'my_function', 10, 1 );
function my_function( $order_id ) {
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $key => $item ) {
// get the data
$storage = wc_get_order_item_meta( $item_id, 'attribute_addon-storage', true );
$tier = wc_get_order_item_meta( $item_id, 'attribute_subscription-type', true );
}
}
After struggling for two days, am now sharing my problem here. I want to save a session value into the meta field of product when product is inserted. currently I am using this code which doesn't work
add_action( 'woocommerce_review_order_after_payment', 'save_product_status_discount', 10, 1 );
function save_product_status_discount($order, $sent_to_admin, $plain_text, $email){
$order_data = $order->get_data();
$item_data = $item_obj->get_data();
$my_post_meta1 = get_post_meta($item_data['order_id'], 'status_discount'.$item_data['order_id'], true);
if(empty ( $my_post_meta1 )){
update_post_meta($item_data['order_id'],'status_discount'.$item_data['order_id'],$_SESSION['status_discount_price']);
}
}
Please help me what should I do. thanks
You could use that, but is not going to work well as you should need to do it for each order item (I think, the correct way is below at the end):
// Save the order meta with field value
add_action( 'woocommerce_checkout_update_order_meta', 'save_product_status_discount', 10, 1 );
function save_product_status_discount( $order_id ) {
$status_discount = get_post_meta($order_id, 'status_discount'.$order_id, true);
if(empty ( $status_discount ) && ! empty( $_SESSION['status_discount_price'] ) )
update_post_meta( $order_id, 'status_discount'.$order_id, $_SESSION['status_discount_price'] );
}
}
// Display the order meta with field value
add_action( 'woocommerce_review_order_after_payment', 'display_product_status_discount', 10, 4 );
function save_product_status_discount($order, $sent_to_admin, $plain_text, $email){
$status_discount = get_post_meta($order_id, 'status_discount'.$order_id, true);
if( ! empty ( $status_discount ) )
echo '<p>'.__( 'Status discount', 'woocommerce' ) . ': ' . $status_discount . '</p>
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
The correct way to do it, is to incorporate this "status discount" as item ID meta data, because you can have many items in an order.
So the best option and working code should be simply that compact function:
// Save the order item meta data with custom field value and display it as order items meta data
add_action('woocommerce_add_order_item_meta','save_product_status_discount', 1, 3 );
function save_product_status_discount( $item_id, $values, $cart_item_key ) {
if( empty( $_SESSION['status_discount_price'] ) )
wc_add_order_item_meta( $item_id, 'Status discount', $_SESSION['status_discount_price'], true );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested in WooCommerce 3+ and works.
I use the Customer/Order CSV Export plugin from WooThemes to export orders from my shop. However I want to add additional data to the CSV output per line item (do some calculations etc.) and I found below information on the official WooThemes page.
However I want to access the line item data, how can I achieve this? For example: How can I get the 'item_total' which is not stored in the postmeta database (the postmeta database is listed in the example below) ?
Is the line_item data included in the $order_data? How can I access it?
function wc_csv_export_modify_row_data( $order_data, $order, $csv_generator ) {
$custom_data = array(
'column_1' => get_post_meta( $order->id, 'some_meta_key', true ),
'column_2' => get_post_meta( $order->id, 'some_other_meta_key', true ),
// add other row data here in the format column_key => data
);
$new_order_data = array();
if ( isset( $csv_generator->order_format ) && ( 'default_one_row_per_item' == $csv_generator->order_format || 'legacy_one_row_per_item' == $csv_generator->order_format ) ) {
foreach ( $order_data as $data ) {
$new_order_data[] = array_merge( (array) $data, $custom_data );
}
} else {
$new_order_data = array_merge( $order_data, $custom_data );
}
return $new_order_data;
}
add_filter( 'wc_customer_order_csv_export_order_row', 'wc_csv_export_modify_row_data', 10, 3 );
you can create an object of WC_Order class by passing order id to it. Using get_items() you will get all items array which are present in that order. After getting an array you may use get_item_meta() for getting each items meta values pass order_item_id to it.
I've managed to code my plugin to add extra custom fields to woocommerce products. This works all the way through from cart to completing an order. Going to my account and viewing past orders, the custom fields are displayed correctly.
However, when I choose to click "order again" on a past order, the new cart doesn't contain the custom fields and their values.
Here is what I currently have to attempt this:
// order again
add_filter( 'woocommerce_order_again_cart_item_data', 'woocommerce_order_again_cart_item_data', 10, 3 );
function woocommerce_order_again_cart_item_data($cart_item_meta, $product, $order){
global $woocommerce;
// Disable validation
remove_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_add_cart_item' ), 10, 3 );
if ( ! array_key_exists( 'item_meta', $cart_item_meta ) || ! is_array( $cart_item_meta['item_meta'] ) )
$cart_item_meta['item_meta'] = array();
foreach ( array( 'jhpc_toppings', 'jhpc_sauce', 'jhpc_toppings_half', 'jhpc_sauce_half', 'jhpc_garnish' ) as $key )
$cart_item_meta['item_meta'][$key] = $product['item_meta'][$key];
return $cart_item_meta;
}
replace
$cart_item_meta['item_meta'][$key] = $product['item_meta'][$key];
by
$cart_item_meta[$key] = $product[$key];
Otherwise, why are you removing the validation ?
Here is the code to add all custom field data for order again. Use the given code in your theme's function.php file and replace the custom field keys of $customfields array with your keys.
<?php
add_filter( 'woocommerce_order_again_cart_item_data', 'wpso2523951_order_again_cart_item_data', 10, 3 );
function wpso2523951_order_again_cart_item_data($cart_item_meta, $product, $order){
//Create an array of all the missing custom field keys that needs to be added in cart item.
$customfields = [
'customfield_key1',
'customfield_key2',
'customfield_key3',
'customfield_key4',
];
global $woocommerce;
remove_all_filters( 'woocommerce_add_to_cart_validation' );
if ( ! array_key_exists( 'item_meta', $cart_item_meta ) || ! is_array( $cart_item_meta['item_meta'] ) )
foreach ( $customfields as $key ){
if(!empty($product[$key])){
$cart_item_meta[$key] = $product[$key];
}
}
return $cart_item_meta;
}
?>
Replace the values of array $customfields with the keys of custom fields that are missing or are not being added automatically.